【BZOJ4976】宝石镶嵌 DP
2017-08-22 14:32
197 查看
【BZOJ4976】宝石镶嵌
Description
魔法师小Q拥有n个宝石,每个宝石的魔力依次为w_1,w_2,...,w_n。他想把这些宝石镶嵌到自己的法杖上,来提升法杖的威力。不幸的是,小Q的法杖上宝石镶嵌栏太少了,他必须扔掉k个宝石才能将剩下的宝石镶嵌上去。法杖的威力等于镶嵌在上面的所有宝石的魔力按位做或(OR)运算的结果,请写一个程序帮助小Q做出最佳的选择,使得法杖的威力最大。Input
第一行包含两个正整数n,k(2<=n<=100000,1<=k<=100,k<n),分别表示宝石的个数以及要扔掉的宝石个数。第二行包含n个整数w_1,w_2,...,w_n(0<=w_i<=100000),分别表示每个宝石的魔力。
Output
输出一行一个整数,即最大的威力。Sample Input
4 132 16 8 7
Sample Output
56题解:考虑如果n-k>=17,那么我们对于每一位都选一个对应位为1的宝石即可。所以我们只需要考虑n-k<17的情况,即n<117。
那么直接背包DP即可,f[i]表示或=i时所需要的最少的数。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn=100010; int n,k,ans; int v[maxn]; int f[maxn<<2]; inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret*f; } int main() { n=rd(),k=rd(); int i,j; for(i=1;i<=n;i++) v[i]=rd(); if(n-k>=16) { for(i=1<<16;i;i>>=1) { for(j=1;j<=n;j++) if(v[j]&i) break; if(j<=n) ans|=i; } printf("%d",ans); return 0; } memset(f,0x3f,sizeof(f)); f[0]=0; for(i=1;i<=n;i++) { for(j=(1<<17)-1;~j;j--) { f[j|v[i]]=min(f[j|v[i]],f[j]+1); } } for(i=(1<<17)-1;~i;i--) { for(j=1<<16;j;j>>=1) if(i&j) f[i^j]=min(f[i^j],f[i]); } for(i=1<<16;i;i>>=1) { if(f[ans|i]<=n-k) ans|=i; } printf("%d",ans); return 0; }
相关文章推荐
- bzoj4976宝石镶嵌 DP
- [bzoj4976][dp]宝石镶嵌
- BZOJ 4976: 宝石镶嵌 背包
- bzoj 4976: 宝石镶嵌 动态规划
- bzoj 4976: 宝石镶嵌
- 【bzoj4976】宝石镶嵌 乱搞+dp
- [bzoj 4976]宝石镶嵌
- [bzoj4976]宝石镶嵌
- BZOJ-4976 (分类+dp)
- BZOJ 1625: [Usaco2007 Dec]宝石手镯( dp )
- BZOJ 1131 [POI2008]Sta 树形DP
- 【bzoj3156】防御准备 斜率优化dp
- [省选前题目整理][BZOJ 1911][APIO 2010]特别行动队(斜率优化DP)
- [省选前题目整理][BZOJ 3675][APIO 2014]序列分割(斜率优化DP)
- [bzoj1084][DP][前缀和]最大子矩阵
- BZOJ 2331 SCOI 2011 地板 插头DP
- bzoj 1575: [Usaco2009 Jan]气象牛Baric【dp】
- [省选前题目整理][BZOJ 1833][ZJOI 2010]count 数字计数(数位DP)
- BZOJ 1606 [Usaco2008 Dec]Hay For Sale 购买干草 DP---背包
- [BZOJ1833][ZJOI2010]Count数字计数(DP)