zoukankan      html  css  js  c++  java
  • BZOJ3324 : [Scoi2013]火柴棍数字

    为了使数字最大,首先要最大化其位数。

    设$f[i][j][k]$表示从低到高考虑了$i$位,手头火柴棍个数为$j$,第$i$位是不是$0$时,最少移动多少根火柴。

    若$f[i][0][非0]leq k$,则存在一个长度为$i$的数,由此可以求出最大长度。

    确定长度之后,再从高到低逐位贪心确定每一位即可。

    时间复杂度$O(nk)$。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=3510;
    int n,m,all,use,len,i,j,k,x;char a[N];
    short f[N/2][N*2][2];
    int S[10]={126,48,107,121,53,93,95,112,127,125},dx[11][10],dy[11][10];
    inline void up(short&x,short y){if(x>y)x=y;}
    int main(){
      for(i=0;i<10;i++)for(j=0;j<10;j++)for(k=0;k<7;k++){
        if(!(S[i]>>k&1)&&(S[j]>>k&1))dx[i][j]++,dy[i][j]++;
        if((S[i]>>k&1)&&!(S[j]>>k&1))dx[i][j]--;
      }
      for(i=0;i<10;i++)for(k=0;k<7;k++)if(S[i]>>k&1)dx[10][i]++,dy[10][i]++;
      scanf("%s%d",a+1,&m);
      n=strlen(a+1);
      reverse(a+1,a+n+1);
      for(i=1;i<=n;i++)a[i]-='0';
      for(i=1;i<=n;i++)all+=dy[10][a[i]];
      len=all/2;
      for(i=n+1;i<=len;i++)a[i]=10;
      for(i=0;i<=len;i++)for(j=-m;j<=m;j++)for(k=0;k<2;k++)f[i][j+N][k]=m+1;
      f[0][N][0]=0;
      for(i=0;i<len;i++)for(j=-m;j<=m;j++)for(k=0;k<2;k++)if(f[i][j+N][k]<=m)
        for(x=0;x<10;x++){
          up(f[i+1][j+N+dx[a[i+1]][x]][x==0],f[i][j+N][k]+dy[a[i+1]][x]);
        }
      while(f[len][N][0]>m)len--;
      for(i=0;i<=len;i++)for(j=-m;j<=m;j++)up(f[i][j+N][0],f[i][j+N][1]);
      for(all=0,i=len;i;i--)for(j=9;~j;j--){
        all+=dx[a[i]][j],use+=dy[a[i]][j];
        if(f[i-1][N-all][0]<=m-use){printf("%d",j);break;}
        all-=dx[a[i]][j],use-=dy[a[i]][j];
      }
      return 0;
    }
    

      

  • 相关阅读:
    斐波那契数列
    进制转换
    求最大公约数伪代码
    2020-2021-1 20201315 《信息安全专业导论》第5周学习总结
    XOR加密
    pep9线下作业
    2020-2021-1 20201226 《信息安全专业导论》第四周学习总结
    内网与外网
    打开word文档时,出现office更新,并且更新报错
    由于找不到mfc100u.dll,无法继续执行代码
  • 原文地址:https://www.cnblogs.com/clrs97/p/7114328.html
Copyright © 2011-2022 走看看