TopCoder SRM 399 Div1 Medium BinarySum
問題
三つの正の整数a,b,cが与えられる。
それぞれを2進数での表現をx,y,zとする。
x,y,zのうち、最も桁数の多いものに合わせて、x,y,zの先頭に0をつめる。
その後で、x,y,zのそれぞれについて、桁の数字を好きに並べ替える。
並べ替えた後でleading zeroがあってもよい。
並べ替えた後、z=x+yが成り立つようにする。
このとき、zの最小値を求めよ。
制約条件
a,b,c≦2^30
方針
動的計画法。
dp[pos][xの1の数][yの1の数][zの1の数][繰り上がりがあるか]
を、下からpos桁目までみたときに、それぞれの数の1の数がx,y,zであり、繰り上がりがあるかないかが決まっているときの、pos桁目までのcの最小値とする。
これをpos+1桁目について、aを0,1どちらにするか、bを0,1どちらにするかを決めて更新していく。
ソースコード
int dp[32][32][32][32][2]; class BinarySum { public: int rearrange(int a, int b, int c) { int x=0,y=0,z=0,n=0; for(;a||b||c;n++){ x+=a&1; y+=b&1; z+=c&1; a/=2; b/=2; c/=2; } memset(dp,-1,sizeof(dp)); dp[0][0][0][0][0]=0; rep(i,n)rep(p,i+1)rep(q,i+1)rep(r,i+1)rep(k,2)if(dp[i][p][q][r][k]>=0){ rep(nx,2)rep(ny,2){ int bit=k+nx+ny; if(dp[i+1][p+nx][q+ny][r+(bit&1)][bit>>1]<0|| dp[i+1][p+nx][q+ny][r+(bit&1)][bit>>1]>dp[i][p][q][r][k]+((bit&1)<<i)) dp[i+1][p+nx][q+ny][r+(bit&1)][bit>>1]=dp[i][p][q][r][k]+((bit&1)<<i); } } return dp[n][x][y][z][0]; } };