前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Day1下午解题报告

Day1下午解题报告

作者头像
attack
发布2018-04-11 16:23:15
7680
发布2018-04-11 16:23:15
举报
文章被收录于专栏:数据结构与算法

预计分数:0+30+30=60

实际分数:0+30+40=70

T1水题(water)

贪心,按长度排序,

对于第一幅牌里面的,在第二个里面,找一个长度小于,高度最接近的牌

进行覆盖。

考场上的我离正解只差一个小于号之遥。。。。。。。

代码语言:javascript
复制
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <set>
 6 using namespace std;
 7 int n;
 8 multiset <int> s;
 9 struct node {int x,y;} a[100005],b[100005];
10 int cmp(node i,node j) {return i.x<j.x;}
11 int main()
12 {
13     freopen("water.in","r",stdin);
14     freopen("water.out","w",stdout);
15     int T;
16     T=1;
17     while(T--)
18     {
19         scanf("%d",&n);
20         for(int i=0;i<n;i++) scanf("%d%d",&a[i].x,&a[i].y);
21         for(int i=0;i<n;i++) scanf("%d%d",&b[i].x,&b[i].y);
22         sort(a,a+n,cmp);
23         sort(b,b+n,cmp);
24         s.clear();
25         int k=0,ans=0;
26         for(int i=0;i<n;i++)
27         {
28             while(a[i].x>=b[k].x&&k<n)
29             {
30                  s.insert(b[k].y);
31                  k++;
32             }
33             if(s.empty())continue;
34             multiset<int>::iterator it=s.upper_bound(a[i].y);
35             if (it==s.begin()) continue; it--;
36             ans++; s.erase(it);
37         }
38         printf("%d\n",ans);
39     }
40     return 0;
41 }

T2下午梦境(dream)

不会做,手玩30分

正解

dp||爆搜

1 2 4 8 ... 1 3 7 15 31 ... int(log(n)/log(2))+1

方案总数:dp,搜索

2^0+2^1+...+2^k = O(n) k=log(n) dfs(Max,Sum,S) // Max金币最大值,Sum所有金币的和,S金币的数量

dp[i][j][k] 当前有i个金币,金币和是j,最大的金币k。

if (dp[i][j][k]) 枚举下一枚金币是啥。

代码语言:javascript
复制
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 const int MAXN=1e6;
 7 inline int read()
 8 {
 9     char c=getchar();int flag=1,x=0;
10     while(c<'0'||c>'9')    {if(c=='-')    flag=-1;c=getchar();}
11     while(c>='0'&&c<='9')     x=x*10+c-48,c=getchar();return x*flag;
12 }
13 int n;
14 int main()
15 {
16     //freopen("dream.in","r",stdin);
17     //freopen("dream.out","w",stdout);
18     n=read();
19     if(n==0)    printf("0 1");
20     if(n==1)    printf("1 1");
21     if(n==2)    printf("2 1");
22     if(n==3)    printf("2 1");
23     if(n==4)    printf("3 1");
24     if(n==5)    printf("3 2");
25     if(n==6)    printf("3 2");
26     if(n==7)    printf("3 1");
27     if(n==8)    printf("4 8");
28     if(n==9)    printf("4 8");
29     if(n==10)    printf("4 8");
30     if(n>10)    printf("5 6");
31     return 0;
32 }
代码语言:javascript
复制
 1 #include <cmath>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <iostream>
 5 #include <algorithm>
 6 using namespace std;
 7 int n,sum,ans,dp[1005][1005],DP[1005][1005],i,j,k,l;
 8 int main()
 9 {
10     freopen("dream.in","r",stdin);
11     freopen("dream.out","w",stdout);
12     scanf("%d",&n);
13     sum=int(log(n)/log(2)+0.000000001)+1;
14     dp[1][1]=1;
15     for (i=1; i<sum; i++)
16     {
17         for (j=1; j<=n; j++)
18           for (k=1; k<=n; k++)
19             if (dp[j][k])
20               for (l=k+1; l<=j+1; l++)
21                 DP[min(n,j+l)][l]+=dp[j][k];
22         for (j=1; j<=n; j++) for (k=1; k<=n; k++) {dp[j][k]=DP[j][k];DP[j][k]=0;}
23     }
24     for (j=1; j<=n; j++) ans+=dp[n][j];
25     cout<<sum<<' '<<ans;
26     return 0;
27 }

T3动态规划(dp)

题目描述

LYK在学习dp,有一天它看到了一道关于dp的题目。

这个题目是这个样子的:一开始有n个数,一段区间的价值为这段区间相同的数的对数。我们想把这n个数切成恰好k段区间。之后这n个数的价值为这k段区间的价值和。我们想让最终这n个数的价值和尽可能少。

例如6个数1,1,2,2,3,3要切成3段,一个好方法是切成[1],[1,2],[2,3,3],这样只有第三个区间有1的价值。因此这6个数的价值为1。

LYK并不会做,丢给了你。

输入输出格式

输入格式:

第一行两个数n,k。

接下来一行n个数ai表示这n个数。

输出格式:

一个数表示答案。

输入输出样例

输入样例#1: 

代码语言:javascript
复制
10 2
1 2 1 2 1 2 1 2 1 2

输出样例#1: 

代码语言:javascript
复制
8

说明

对于30%的数据n<=10。

对于60%的数据n<=1000。

对于100%的数据1<=n<=100000,1<=k<=min(n,20),1<=ai<=n。

其中有30%的数据满足ai完全相同均匀分布在所有数据中。

考场上我想出60分的dp了

但是我感觉不对,直觉告诉我一定不对,。

但实际上是对的mmp。。。。。

打了30分暴力走人,,

正解:

dp[i][j] 1~i 切了j刀,的最优解

dp[i][j]=min{dp[k][j-1]+sum(k+1,i)}

可以证明这个转移方程具有单调性

20*n^2的简单dp -> 在固定j的情况下 随着i的增大,k不降 -> 分治求dp值

代码语言:javascript
复制
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #define N 1000011
 5 #define min(x, y) ((x) < (y) ? (x) : (y))
 6 #define max(x, y) ((x) > (y) ? (x) : (y))
 7 using namespace std;
 8 int n, q, ans;
 9 int f[N];
10 
11 struct node
12 {
13     int x, y, z;
14 }p[N], t[N];
15 
16 inline int read()
17 {
18     int x = 0, f = 1;
19     char ch = getchar();
20     for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
21     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
22     return x * f;
23 }
24 
25 inline bool cmp(node x, node y)
26 {
27     return x.z > y.z;
28 }
29 
30 inline int find(int x)
31 {
32     return x == f[x] ? x : f[x] = find(f[x]);
33 }
34 
35 inline bool check(int k)
36 {
37     int i, j, x, y, lmin, lmax, rmin, rmax;
38     for(i = 1; i <= n + 1; i++) f[i] = i;
39     for(i = 1; i <= k; i++) t[i] = p[i];
40     std::sort(t + 1, t + k + 1, cmp);
41     lmin = lmax = t[1].x;
42     rmin = rmax = t[1].y;
43     for(i = 2; i <= k; i++)
44     {
45         if(t[i].z < t[i - 1].z)
46         {
47             if(find(lmax) > rmin) return 1;
48             for(j = find(lmin); j <= rmax; j++)
49                 f[find(j)] = find(rmax + 1);
50             lmin = lmax = t[i].x;
51             rmin = rmax = t[i].y;
52         }
53         else
54         {
55             lmin = min(lmin, t[i].x);
56             lmax = max(lmax, t[i].x);
57             rmin = min(rmin, t[i].y);
58             rmax = max(rmax, t[i].y);
59             if(lmax > rmin) return 1;
60         }
61     }
62 //    cout<<find(1)<<endl;
63     if(find(lmax) > rmin) return 1;
64     return 0;
65 }
66 
67 int main()
68 {
69     freopen("number.in","r",stdin);
70     freopen("number.out","w",stdout);
71     int i, x, y, mid;
72     n = read();
73     q = read();
74     for(i = 1; i <= q; i++)
75         p[i].x = read(), p[i].y = read(), p[i].z = read();
76     x = 1, y = q;
77     //cout<<check(2)<<endl;
78     //return 0;
79     ans = q + 1;
80     while(x <= y)
81     {
82         mid = (x + y) >> 1;
83         if(check(mid)) ans = mid, y = mid - 1;
84         else x = mid + 1;
85     }
86     printf("%d\n", ans);
87     return 0;
88 }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-10-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 预计分数:0+30+30=60
  • 实际分数:0+30+40=70
  • T1水题(water)
  • T2下午梦境(dream)
  • T3动态规划(dp)
    • 题目描述
      • 输入输出格式
        • 输入输出样例
          • 说明
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档