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\n";
#else
    const char LL[]="%lld\n";
#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;
}

 

 

 

posted @ 2018-09-14 20:03  Gloid  阅读(128)  评论(0编辑  收藏  举报