2017/8/15 考试吐槽

2017 8 15 得分:15

爆零快乐~

A、字符合并

链接:http://cogs.pro/cogs/problem/problem.php?pid=2269

题意:每个一定长度$0-1$串可以转化成一个二进制数字求出一个$0-1$串转化。

考试时第一遍集体爆零……最后发现测试点还是$HAOI2016$锅了的测试点……

正解是状压……写的很详细的代码注释……自己取吧……

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=305,maxa=1<<9;
 7 long long f[maxn][maxn][2],c[maxn],v[maxn],a[maxn],g[maxn][maxa],now,tmp[3],ans[maxn];
 8 /*我们这里的f数组与其他的f数组并不完全相同,这里的f数组第三维严格地讲只是半维,0/1表示这个串全部变为0/1可以获得的最大积分;
 9 相应的g数组第二维从半维变成整维,第二维代替了f数组本应该存在的存储最近8位状态的第三维,g数组也就改变了意义,g[i][j]变为转移到i这个长度,最后几位状态为j下最大收益;
10 然后,这个tmp数组中的tmp[i]也就表示了所有可以转化到i的01串转化后连带前面的串可以获得的最大收益。*/
11 int N,K;
12 int haha()
13 {
14     //freopen("merge_2016.in","r",stdin);
15     //freopen("merge_2016.out","w",stdout);
16     scanf("%d%d",&N,&K);//输入
17     int att=(1<<K);//确定最大状态
18     memset(f,-1,sizeof(f));//初始化记忆化表格
19     for(int i=1;i<=N;i++)//输入01串
20     {
21         scanf("%1d",&a[i]);
22         f[i][i][a[i]]=0;//已经合适,就不需要修改
23     }
24     for(int i=0;i<att;i++)scanf("%d%d",&c[i],&v[i]);//每一种修改的情况
25     for(int i=N-K+1;i>=1;i--)//可以搞这么多轮,从后往前合并
26     {
27         memset(g,-1,sizeof(g));//初始化
28         now=1;g[i][0]=f[i][i][0];g[i][1]=f[i][i][1];//从i开始的串最后一位状态为0、1的情况已经确定了
29         for(int j=i+1;j<=N;j++)
30         {
31             for(int s=0;s<(1<<now);s++)//枚举状态
32                 if(g[j-1][s]>=0)//这一状态是合法的
33                     for(int k=j;k<=N;k+=K-1)//每k个为一段判断
34                     {
35                         if(f[j][k][0]>=0)g[k][s<<1]=max(g[k][s<<1],g[j-1][s]+f[j][k][0]);//可以合成0就合成0
36                         if(f[j][k][1]>=0)g[k][s<<1|1]=max(g[k][s<<1|1],g[j-1][s]+f[j][k][1]);//可以合成1就合成1,其实这里就是一个区间dp
37                     }
38             if(++now==K)//长度够了
39             {
40                 tmp[0]=tmp[1]=-1;//初始化转化到尾巴的情况
41                 for(int k=0;k<(1<<now);k++)
42                     if(g[j][k]>=0)tmp[c[k]]=max(tmp[c[k]],v[k]+g[j][k]);//这个状态是可以构建出来的,就更新以目标字符结尾的结果
43                 f[i][j][1]=g[j][1]=tmp[1];//更新结果
44                 f[i][j][0]=g[j][0]=tmp[0];
45                 now=1;
46             }
47         }
48     }
49     for(int i=1;i<=N;i++)
50         for(int j=i;j<=N;j+=K-1)ans[j]=max(ans[j],ans[i-1]+max(f[i][j][1],f[i][j][0]));//每一个都可以合并,能合就合
51     printf("%lld\n",ans[N]);
52 }
53 int sb=haha();
54 int main(){;}
A

B、就

题意:给出一个填了一部分的矩阵,问存不存在非负整数填法使得每个$2*2$子矩阵满足左上加右下等于右上加左下。

考试只得了$10$分特判……

我们差分一下就可以发现:每一列差相等。于是我们就可以维护带权并查集,竖着一组横着一组……然后判断差分合不合法、最小解是否非负即可……

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn=100005;
 7 int fa[maxn],fa2[maxn];long long w1[maxn],w2[maxn];
 8 struct node
 9 {
10     int x,y,val;
11     void read()
12     {
13         scanf("%d%d%d",&x,&y,&val);
14     }
15 }P[maxn];
16 bool cmpx(const node &a,const node &b)
17 {
18     return a.x<b.x;
19 }
20 bool cmpy(const node &a,const node &b)
21 {
22     return a.y<b.y;
23 }
24 int getfa1(int x)
25 {
26     if(x==fa[x])return x;
27     int rt=getfa(fa[x]);w1[x]+=w1[fa[x]];return fa[x]=rt;
28 }
29 int getfa2(int x)
30 {
31     if(x==fa2[x])return x;
32     int rt=getfa2(fa2[x]);w2[x]+=w2[fa2[x]];return fa2[x]=rt;
33 }
34 bool unionn1(int a,int b,long long w)
35 {
36     if(getfa1(a)!=getfa1(b))
37     {
38         a=getfa1(a),b=getfa1(b);
39         fa[a]=fa[b];w1[a]=w+w1[b]-w1[a];
40         return 1;
41     }
42     else return w1[a]==w+w1[b];
43 }
44 bool unionn2(int a,int b,long long w)
45 {
46     if(getfa2(a)!=getfa2(b))
47     {
48         a=getfa2(a),b=getfa2(b);
49         fa2[a]=fa2[b];w2[a]=w+w2[b]-w2[a];
50         return 1;
51     }
52     else return w2[a]==w+w2[b];
53 }
54 long long min1[maxn],min2[maxn];
55 int haha()
56 {
57     freopen("then.in","r",stdin);
58     freopen("then.out","w",stdout);
59     int tests;scanf("%d",&tests);
60     while(tests--)
61     {
62         bool tt=1;
63         int r,c;scanf("%d%d",&r,&c);
64         for(int i=1;i<=r;i++)fa[i]=i,w1[i]=0;
65         for(int i=1;i<=c;i++)fa2[i]=i,w2[i]=0;
66         int n;scanf("%d",&n);
67         for(int i=1;i<=n;i++)P[i].read();
68         for(int i=1;i<=n;i++)if(P[i].val<0)tt=0;
69         sort(P+1,P+n+1,cmpx);
70         for(int i=1;i<n;i++)
71             if(P[i].x==P[i+1].x)
72                 if(!unionn2(P[i].y,P[i+1].y,P[i+1].val-P[i].val))tt=0;
73         sort(P+1,P+n+1,cmpy);
74         for(int i=1;i<n;i++)
75             if(P[i].y==P[i+1].y)
76                 if(!unionn1(P[i].x,P[i+1].x,P[i+1].val-P[i].val))tt=0;
77         memset(min1,0x3f,sizeof(min1));
78         memset(min2,0x3f,sizeof(min2));
79         for(int i=1;i<=n;i++)
80         {
81             int rt=getfa1(P[i].x);
82             min1[rt]=min(min1[rt],P[i].val+w1[P[i].x]);
83         }
84         for(int i=1;i<=r;i++)
85         {
86             int rt=getfa1(i);
87             min2[rt]=min(min2[rt],-w1[i]);
88         }
89         for(int i=1;i<=r;i++)
90             if(fa[i]==i&&min1[i]+min2[i]<0)tt=0;
91         if(tt==1)puts("Yes");else puts("No");
92     }
93 }
94 int sb=haha();
95 int main(){;}
B

C、做

题意:使魔法伤害为两点欧几里得距离平方,每次曼哈顿距离可以减少$2$求被干的人使用最优策略会不会死。

日常爆零……

然后发现自己本来可以$A$的=  =就是个大模拟……

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cstdlib>
 6 #include<ctime>
 7 using namespace std;
 8 const int maxn=305,maxh=205;
 9 long long f[maxn][maxn][maxh];
10 void change(int &x,int &y)
11 {
12     int dis1=2*(x+y)-2,dis2=4*x-4,dis3=4*y-4;
13     int dis=max(dis1,max(dis2,dis3));
14     if(dis==dis1)x--,y--;else if(dis==dis2)x-=2;else y-=2;
15 }
16 int haha()
17 {
18     //freopen("do3.in","r",stdin);
19     //freopen("do.out","w",stdout);
20     int t,a,b;scanf("%d",&t);scanf("%d%d",&a,&b);
21     while(t--)
22     {
23         int x1,y1,x2,y2,c;long long d;scanf("%d%d%d%d%d%lld",&x1,&y1,&x2,&y2,&c,&d);
24         x2-=x1;y2-=y1;x2=abs(x2);y2=abs(y2);int dis=x2+y2;
25         while(dis>0&&d>=0)
26         {
27             if(c>=a)d-=y2*y2+x2*x2,c-=a;else c+=b;
28             dis-=2;
29             change(x2,y2);
30             if(d<=0)break;
31         }
32         if(d<=0)puts("NAIVE");
33         else puts("SIMPLE");
34     }
35 }
36 int sb=haha();
37 int main(){;}
C

 

posted @ 2017-08-15 21:23  ccc000111  阅读(151)  评论(0编辑  收藏  举报