[noip模拟赛]二进制(dp)
来源:互联网 发布:诸葛诞 知乎 编辑:程序博客网 时间:2024/04/29 02:56
题目描述
题解
30分的话暴力就可以,100分考虑dp。
求出ABC中最长的len了之后,就是相当于XY都有len个空缺来填数,可以填0/1,要保证最终填出来的XY中1的个数分别和AB相同,X+Y的长度不超过len,并且X+Y中1的个数与C相同。
设f[i][j][k][l]表示填到第i个空,X中填了k个1,Y中填了l个1,X+Y的长度不超过len,并且X+Y中有j个1的最小的Z=X+Y。
那么转移就很好写了,预处理出来2的幂,每次用f[i-1][j][k][l],f[i-1][j][k-1][l]+mi[i-1],f[i-1][j][k][l-1]+mi[i-1],f[i-1][j][k-1][l-1]+2*mi[i-1]去更新f[i][?][k][l]。注意这里?表示的是要具体算一下更新的最小值Z中的1的个数。
还需要注意的就是由合法的状态转移,还有边界。
代码
#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define N 50#define inf 2147483647int T,A,B,C,Z,len,ans;int f[N][N][N][N],mi[N];struct hp{int len,sum;}a,b,c,z;inline void clear(){ A=B=C=Z=len=0;}inline hp dig(int x){ hp re; int sum=0,len=0; if (!x) return re=(hp){1,0}; for (;x;x>>=1) sum+=x&1,len++; return re=(hp){len,sum};}inline int Max(int a,int b,int c){ if (b>a) a=b; if (c>a) a=c; return a;}int main(){ freopen("binary.in","r",stdin); freopen("binary.out","w",stdout); scanf("%d",&T); mi[0]=1; for (int i=1;i<=31;++i) mi[i]=mi[i-1]*2; while (T--) { clear(); scanf("%d%d%d",&A,&B,&C); a=dig(A),b=dig(B),c=dig(C); len=Max(a.len,b.len,c.len); for (int i=0;i<=35;++i) for (int j=0;j<=35;++j) for (int k=0;k<=35;++k) for (int l=0;l<=35;++l) f[i][j][k][l]=inf; f[0][0][0][0]=0; for (int i=1;i<=len;++i) for (int j=0;j<=min(c.sum,i);++j) for (int k=0;k<=min(a.sum,i);++k) for (int l=0;l<=min(b.sum,i);++l) { if (f[i-1][j][k][l]!=inf) { Z=f[i-1][j][k][l]; z=dig(Z); if (z.len<=len) f[i][z.sum][k][l]=min(f[i][z.sum][k][l],Z); } if (k!=0&&f[i-1][j][k-1][l]!=inf) { Z=f[i-1][j][k-1][l]+mi[i-1]; z=dig(Z); if (z.len<=len) f[i][z.sum][k][l]=min(f[i][z.sum][k][l],Z); } if (l!=0&&f[i-1][j][k][l-1]!=inf) { Z=f[i-1][j][k][l-1]+mi[i-1]; z=dig(Z); if (z.len<=len) f[i][z.sum][k][l]=min(f[i][z.sum][k][l],Z); } if (k!=0&&l!=0&&f[i-1][j][k-1][l-1]!=inf) { Z=f[i-1][j][k-1][l-1]+2*mi[i-1]; z=dig(Z); if (z.len<=len) f[i][z.sum][k][l]=min(f[i][z.sum][k][l],Z); } } ans=inf; for (int i=1;i<=len;++i) ans=min(ans,f[i][c.sum][a.sum][b.sum]); if (ans!=inf) printf("%d\n",ans); else puts("-1"); }}
总结
1、看来字符串dp的套路还是很深啊。
1 0
- [noip模拟赛]二进制(dp)
- [noip模拟赛]祖先(dp)
- [noip模拟赛]敲砖块(dp)
- #NOIP模拟赛#排列问题(DP)
- #NOIP模拟赛#TSP(树型DP)
- #NOIP模拟赛#相似字符串(树形DP + 状压)
- #NOIP模拟赛#押韵rhyme(TRI树 + Dp)
- 2017NOIP模拟赛 葡萄(状压DP)
- #NOIP模拟赛#Cool子集(Dp + 状压)
- 【NOIP 模拟题】掷骰子(dp)
- 【NOIP 模拟题】[T1] 等差数列(dp)
- (noip 模拟 染色)<树形DP>
- 【NOIP模拟】赤壁情(DP)
- NOIP模拟:乘积(状压DP)
- [NOIP 模拟]潜水员 DP
- 【NOIp模拟】【dp】俄罗斯方块
- 【NOIP 模拟题】[山东多校联合模拟赛 day1 T2] 祖先(dp)
- #bzoj2933#【重庆市NOIP模拟赛】数据(DP线段树优化 or DP堆优化 + 证明)
- jquery为动态的节点添加事件
- CNN网络量化 - Quantized Convolutional Neural Networks for Mobile Devices
- 【Consul】Consul实践指导-RPC机制
- java学习之路
- git clone 远程分支
- [noip模拟赛]二进制(dp)
- 后台通用参数校验(JS303规范)
- Session与的Cookie的联系与区别
- Insert Delete GetRandom O(1)
- 程序员基础东东
- Javascript获取select下拉框选中的的值
- 设置ssh连接超时
- 关于Apache Shiro权限框架的一些使用误区的解释
- AVL Tree