预计分数: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("%dn",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("%dn", ans);
87 return 0;
88 }