• 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
    ",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
  • 相关阅读:
    lamp
    Mysql主从
    Mysql多实例部署
    Xtrabackup备份与恢复
    Mysql备份工具mysqldump
    Mysql进阶
    Mysql基础
    MySql进阶管理备份操作和Xtrabackup使用
    MySql的基础配置和操作
    java学习——基础入门(2)
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7367839.html
Copyright © 2020-2023  润新知