bzoj 3107: [cqoi2013]二进制a+b 数位dp
2017-09-23 21:20
302 查看
题意
输入三个整数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
分析
很容易想到dp:f[i,j,k,l,0/1]表示从低位到高位的前i位中,a’用了j个1,b’用了k个1,c’用了l个1,且对c’的下一位是否有进位时c’的最小值。直接暴力转移即可。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define inf 0x7fffffff using namespace std; int bin[35],a,b,c,f[35][35][35][35][2]; void updata(int &d,int x) { d=min(d,x); } int main() { bin[0]=1; for (int i=1;i<=30;i++) bin[i]=bin[i-1]*2; scanf("%d%d%d",&a,&b,&c); int len=0,s1=0,s2=0,s3=0; for (int i=0;i<=30;i++) { if (a&bin[i]) s1++,len=i+1; if (b&bin[i]) s2++,len=i+1; if (c&bin[i]) s3++,len=i+1; } for (int i=0;i<=len;i++) for (int j=0;j<=s1;j++) for (int k=0;k<=s2;k++) for (int l=0;l<=s3;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<len;i++) for (int j=0;j<=s1;j++) for (int k=0;k<=s2;k++) for (int l=0;l<=s3;l++) { if (f[i][j][k][l][0]<inf) { updata(f[i+1][j][k][l][0],f[i][j][k][l][0]); if (j<s1&&l<s3) updata(f[i+1][j+1][k][l+1][0],f[i][j][k][l][0]+bin[i]); if (k<s2&&l<s3) updata(f[i+1][j][k+1][l+1][0],f[i][j][k][l][0]+bin[i]); if (j<s1&&k<s2) updata(f[i+1][j+1][k+1][l][1],f[i][j][k][l][0]); } if (f[i][j][k][l][1]<inf) { if (l<s3) updata(f[i+1][j][k][l+1][0],f[i][j][k][l][1]+bin[i]); if (j<s1) updata(f[i+1][j+1][k][l][1],f[i][j][k][l][1]); if (k<s2) updata(f[i+1][j][k+1][l][1],f[i][j][k][l][1]); if (j<s1&&k<s2&&l<s3) updata(f[i+1][j+1][k+1][l+1][1],f[i][j][k][l][1]+bin[i]); } } if (f[len][s1][s2][s3][0]==inf) puts("-1"); else printf("%d",f[len][s1][s2][s3][0]); return 0; }
相关文章推荐
- [二进制构造 || DP] BZOJ 3107 [cqoi2013]二进制a+b
- BZOJ 3107 [cqoi2013]二进制a+b (DP)
- [BZOJ3107][CQOI2013]二进制a+b(DP)
- 【BZOJ3107】【cqoi2013】二进制a+b
- BZOJ 3107 [cqoi 2013] DP 解题报告
- 【BZOJ 3107】【CQOI 2013】二进制a+b
- BZOJ3107 CQOI2013二进制A+B(动态规划)
- BZOJ 3107 CQOI2013 二进制a+b 构造
- BZOJ 3107 [cqoi2013]二进制a+b 分类讨论
- bzoj 3107: [cqoi2013]二进制a+b 构造
- [bzoj3107][CQOI2013]二进制a+b
- bzoj 4521: [Cqoi2016]手机号码【数位dp】
- 【BZOJ4521】【CQOI2016】手机号码 数位DP
- bzoj 3131 [Sdoi2013]淘金(数位dp)
- 【bzoj4521】【CQOI2016】【手机号码】【数位dp】
- [BZOJ4521][CQOI2016] 手机号码 - 数位DP
- [Bzoj3131][Sdoi2013]淘金(数位dp)(优先队列)
- [BZOJ4521][CQOI2016]手机号码(数位DP)
- BZOJ 4521: [Cqoi2016]手机号码 数位dp
- [BZOJ3131][Sdoi2013]淘金(数位DP+贪心+堆)