zoukankan      html  css  js  c++  java
  • BZOJ3107 CQOI2013二进制A+B(动态规划)

      显然答案只与a、b、c中各自1的个数及位数有关。a、b只考虑前i位怎么填时,c最多在第i+1位上为1,而第i+1位及之后的a、b怎么填都不会对前i位造成影响。于是设f[n][i][j][k][0/1]表示只考虑前n位,a用i个1,b用j个1,c用k个1,且c的第n+1位为0/1时的最小值。转移时枚举下一位a和b各自填0还是1即可。注意230是有31位的,防止爆int。本来输出的时候是三目运算符的结果发现-1会输出成232-1。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 32
    #define int unsigned int
    #define inf ((1<<31)-1)
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int a,b,c,n,f[N][N][N][N][2];
    inline void update(int &x,int y){x=min(x,y);}
    signed main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3107.in","r",stdin);
        freopen("bzoj3107.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        a=read(),b=read(),c=read();
        int t=0,cnt=0;
        while (a) t++,cnt+=a&1,a>>=1;
        n=max(n,t);a=cnt;
        t=0,cnt=0;
        while (b) t++,cnt+=b&1,b>>=1;
        n=max(n,t);b=cnt;
        t=0,cnt=0;
        while (c) t++,cnt+=c&1,c>>=1;
        n=max(n,t);c=cnt;
        for (int i=0;i<=n;i++)
            for (int j=0;j<=a;j++)
                for (int k=0;k<=b;k++)
                    for (int l=0;l<=c;l++)
                    f[i][j][k][l][0]=f[i][j][k][l][1]=inf;
        f[0][0][0][0][0]=0;
        for (int i=0;i<n;i++)
            for (int j=0;j<=min(a,i);j++)
                for (int k=0;k<=min(b,i);k++)
                    for (int l=0;l<=min(c,i+1);l++)
                    {
                        update(f[i+1][j][k][l][0],min(f[i][j][k][l][0],f[i][j][k][l][1]));
                        update(f[i+1][j+1][k][l+1][0],f[i][j][k][l][0]+(1<<i));
                        update(f[i+1][j][k+1][l+1][0],f[i][j][k][l][0]+(1<<i));
                        update(f[i+1][j+1][k][l][1],f[i][j][k][l][1]+(1<<i));
                        update(f[i+1][j][k+1][l][1],f[i][j][k][l][1]+(1<<i));
                        if (i+1<n) update(f[i+1][j+1][k+1][l+1][1],min(f[i][j][k][l][0],f[i][j][k][l][1])+(1<<i+1));
                    }
        if (f[n][a][b][c][0]==inf) cout<<-1;
        else cout<<f[n][a][b][c][0];
        return 0;
    }

     

  • 相关阅读:
    B-S 期权定价模型
    可转债溢价率
    队列模拟递归遍历目录(广度遍历)
    栈模拟递归遍历目录(深度遍历)
    什么人适合学习Django?
    Python学习笔记———递归遍历多层目录
    树莓派开机自启动程序的设置,两步即可。
    7行代码对百万张照片统一改名。
    tornado上帝视角第一次建立WEB服务器
    武沛齐模态对话框课堂作业
  • 原文地址:https://www.cnblogs.com/Gloid/p/9648414.html
Copyright © 2011-2022 走看看