bzoj3107 [cqoi2013]二进制a+b

Description


输入三个整数a, b, c,把它们写成无前导0的二进制整数。比如a=7, b=6, c=9,写成二进制为a=111, b=110, c=1001。接下来以位数最多的为基准,其他整数在前面添加前导0,使得a, b, c拥有相同的位数。比如在刚才的例子中,添加完前导0后为a=0111, b=0110, c=1001。最后,把a, b, c的各位进行重排,得到a’, b’, c’,使得a’+b’=c’。比如在刚才的例子中,可以这样重排:a’=0111, b’=0011, c’=1010。
你的任务是让c’最小。如果无解,输出-1。

a,b,c<=2^30

Solution


一开始以为是从高位到低位的贪心,没想到是数位dp

设f[I,j,k,l,0/1]表示前i位a用了j个1、b用了k个1、c用了l个1、下一位有没有进位的最小c值,转移的时候大力转移即可,注意不要漏了三个数都不添的情况
实际上应该不用开LL的,实际上可以不用写得这么冗长
onenote真是太好用辣

Code


#include 
#include 
#include 
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))

typedef long long LL;
const int INF=0x7fffffff;

LL f[32][32][32][32][2];
int tot1,tot2,tot3;
int a,b,c,len;

int get_len(int x) {
    int ret=0;
    for (int i=x;i;i/=2) ret++;
    return ret;
}

int main(void) {
    scanf("%d%d%d",&a,&b,&c);
    rep(i,0,30) {
        tot1+=(a&(1<0;
        tot2+=(b&(1<0;
        tot3+=(c&(1<0;
    }
    len=std:: max(len,get_len(a));
    len=std:: max(len,get_len(b));
    len=std:: max(len,get_len(c));
    rep(i,0,len) rep(j,0,tot1) rep(k,0,tot2) rep(l,0,tot3) f[i][j][k][l][0]=f[i][j][k][l][1]=INF;
    f[0][0][0][0][0]=0;
    rep(i,0,len-1) {
        rep(j,0,tot1) rep(k,0,tot2) rep(l,0,tot3) {
            if (f[i][j][k][l][0]!=INF) {
                f[i+1][j][k][l][0]=std:: min(f[i+1][j][k][l][0],f[i][j][k][l][0]);
                if (j1][j+1][k][l+1][0]=std:: min(f[i][j][k][l][0]+(1<1][j+1][k][l+1][0]);
                if (k1][j][k+1][l+1][0]=std:: min(f[i][j][k][l][0]+(1<1][j][k+1][l+1][0]);
                if (j1][j+1][k+1][l][1]=std:: min(f[i][j][k][l][0],f[i+1][j+1][k+1][l][1]);
            }
            if (f[i][j][k][l][1]!=INF) {
                if (l1][j][k][l+1][0]=std:: min(f[i][j][k][l][1]+(1<1][j][k][l+1][0]);
                if (j1][j+1][k][l][1]=std:: min(f[i][j][k][l][1],f[i+1][j+1][k][l][1]);
                if (k1][j][k+1][l][1]=std:: min(f[i][j][k][l][1],f[i+1][j][k+1][l][1]);
                if (j1][j+1][k+1][l+1][1]=std:: min(f[i][j][k][l][1]+(1<1][j+1][k+1][l+1][1]);
            }
        }
    }
    if (f[len][tot1][tot2][tot3][0]==INF) puts("-1");
    else printf("%lld\n", f[len][tot1][tot2][tot3][0]);
    return 0;
}

来自 https://www.lydsy.com/JudgeOnline/problem.php?id=3107

你可能感兴趣的:(c++,数位dp)