洛谷1633 二进制
来源:互联网 发布:java 后端 面试 经验 编辑:程序博客网 时间:2024/06/17 13:36
题目描述
有三个整数A、B、C,以下用N(2)表示N的二进制(没有前导0)。
设A(2)、B(2)、C(2)的最大长度为L,你需要构造三个正整数X、Y、Z,满足以下条件:
(1) X(2)、Y(2)、Z(2)的长度都不超过L。
(2) A(2)与X(2)中1的个数相同。
(3) B(2)与Y(2)中1的个数相同。
(4) C(2)与Z(2)中1的个数相同。
(5) X+Y=Z。
传送门
算法
这是一道数位DP题。
自然想到用
首先考虑
首先,若这一位X、Y都选0,那么Z这一位也是0,且没有进位:
0……+ 0……------- 0……得f[i+1][a][b][c][0]=min(f[i+1][a][b][c][0],f[i][a][b][c][0])
其次,若X和Y这一位都要选,那么Z这一位就是0,但是要进位:
1……+ 1……------- 10……则f[i+1][a+1][b+1][c][1]=min(f[i+1][a+1][b+1][c][1],f[i][a][b][c][0]+(1<<i))
然后,若X选Y不选,那么Z这一位就是1,且不进位:
1……+ 0……------- 1……则f[i+1][a+1][b][c+1][0]=min(f[i+1][a+1][b][c+1][0],f[i][a][b][c][0]+(1<<i-1))
最后,若X不选Y选,那么同上。
0……+ 1……------- 1……则f[i+1][a][b+1][c+1][0]=min(f[i+1][a][b+1][c+1][0],f[i][a][b][c][0]+(1<<i-1))
然后考虑
首先,若这一位X、Y都选0,那么Z这一位是1(有进位),且没有进位:
0……+ 0……------- 1……得f[i+1][a][b][c+1][0]=min(f[i+1][a][b][c+1][0],f[i][a][b][c][1])
其次,若X和Y这一位都要选,那么Z这一位还是1,而且要进位:
1……+ 1……------- 11……则f[i+1][a+1][b+1][c+1][1]=min(f[i+1][a+1][b+1][c+1][1],f[i][a][b][c][1]+(1<<i))
然后,若X选Y不选,那么Z这一位就是0,且进位:
1……+ 0……------- 10……则f[i+1][a+1][b][c][1]=min(f[i+1][a+1][b][c][1],f[i][a][b][c][1]+(1<<i-1))
最后,若X不选Y选,那么同上。
0……+ 1……------- 10……则f[i+1][a][b+1][c][1]=min(f[i+1][a][b+1][c][1],f[i][a][b][c][1]+(1<<i-1))
(如有手打错误还请指正)
注意判断无解,方法是把没有的状态置为INF。
边界为
代码
#include <algorithm>#include <iostream>#include <cstdlib>#include <cstring>#include <cstdio>#define re registerusing namespace std;int l;inline int Bit(int k) //求二进制1的个数顺便更新长度{ int s=0,tl=0; for (;k;k>>=1,++tl) s+=k&1; if (tl>l) l=tl; return s;}inline int read() //读优{ int X=0,w=1; char ch=getchar(); while (ch<'0'||ch>'9') { if (ch=='-') w=-1; ch=getchar(); } while (ch>='0'&&ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar(); return X*w;}inline void GetMin(int& a,int b) { if (b<a) a=b; } //就是a=min(a,b)的功能int f[40][40][40][40][2]; //DP数组int main(){ int t; t=read(); while (t--) { //t组数据 l=0; int A=read(),B=read(),C=read(); A=Bit(A),B=Bit(B),C=Bit(C); //数据+处理 memset(f,0x7f,sizeof(f)); //置INF int INF=f[1][0][0][0][0]; //记录一下INF f[1][0][0][0][0]=0; //边界 for (re int i=1;i<=l;i++) //DP for (re int a=0;a<=A;a++) for (re int b=0;b<=B;b++) for (re int c=0;c<=C;c++) { int t; t=f[i][a][b][c][0]; if (t<INF) { //状态存在 GetMin(f[i+1][a][b][c][0],t); GetMin(f[i+1][a+1][b+1][c][1],t+(1<<i)); GetMin(f[i+1][a+1][b][c+1][0],t+(1<<(i-1))); GetMin(f[i+1][a][b+1][c+1][0],t+(1<<(i-1))); } t=f[i][a][b][c][1]; if (t<INF) { //状态存在 GetMin(f[i+1][a][b][c+1][0],t); GetMin(f[i+1][a+1][b+1][c+1][1],t+(1<<i)); GetMin(f[i+1][a+1][b][c][1],t+(1<<(i-1))); GetMin(f[i+1][a][b+1][c][1],t+(1<<(i-1))); } } if (f[l+1][A][B][C][0]!=INF) printf("%d\n",f[l+1][A][B][C][0]); //有解就输出 else printf("-1\n"); //无解 } return 0;}
阅读全文
0 0
- 洛谷1633 二进制
- 洛谷 P2104 二进制
- 洛谷 P1633 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 二进制
- 明文密码
- Period UVA
- php中的in_array(),array_keys(),array_column()
- TimeUtils 有关时间处理的工具类
- Java多线程的三种实现方法
- 洛谷1633 二进制
- opencv-视频入门
- BufferedInputStream与BufferedOutputStream用法简介
- clone-graph Java code
- 在zxing带三方包里添加打开摄像头灯光功能
- Socket通信
- CCF CSP认证考试历年真题 模板生成系统 C语言实现
- 手把手教你将Vim改装成一个IDE编程环境(图文)
- python--map函数