[DP]BZOJ 1190——[HNOI2007]梦幻岛宝珠 动态规划]
2017-10-06 16:16
387 查看
题目梗概
一个背包问题,但是有一些奇怪的条件。背包大小<=230 N<=100
物品符合a∗2b(a<=10;b<=30)
题目梗概
把背包大小看成一个二进制数。将f[i][j]定义为前i位数,2i这位选择了j个大小。
枚举第i−1位填k,显然剩下的j−k都由第i位填满,所以可以得到转移方程f[i][j]=max(f[i][j],f[i][j−k]+f[i−1][min(2∗k+((w>>i−1)&1),m)])
m为i−1的上限,因为a<=10,所以m=1000
这也是这么定义DP的好处,j,k的上限为m
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int m=1000; int w,n,f[35][m+5],ans; int main(){ freopen("exam.in","r",stdin); freopen("exam.out","w",stdout); while(1){ scanf("%d%d",&n,&w); if (n==-1&&w==-1) return 0; memset(f,0,sizeof(f)); for (int i=1,a,x,b;i<=n;i++){ scanf("%d%d",&a,&x);b=0; while(a%2==0) a>>=1,b++; for (int j=m;j>=a;j--) f[b][j]=max(f[b][j],f[b][j-a]+x); } ans=0;for (int j=0;j<=m;j++) ans=max(f[0][j],ans); for (int i=1;i<=30&&(1<<i)<=w;i++) for (int j=min(m,w>>i);j>=0;j--){ for (int k=0;k<=j;k++) f[i][j]=max(f[i][j],f[i][j-k]+f[i-1][min(2*k+((w>>i-1)&1),m)]); ans=max(ans,f[i][j]); } printf("%d\n",ans); } }
相关文章推荐
- 【bzoj1190】[HNOI2007]梦幻岛宝珠 分层背包dp
- BZOJ 1190: [HNOI2007]梦幻岛宝珠 背包DP
- bzoj1190 [HNOI2007]梦幻岛宝珠 ( 二进制分组优化背包DP)
- [数位DP] BZOJ1190. [HNOI2007]梦幻岛宝珠
- 【BZOJ1190】[HNOI2007]梦幻岛宝珠 分层背包DP
- BZOJ 1190 HNOI2007 梦幻岛宝珠 动态规划
- [bzoj1190][HNOI2007]梦幻岛宝珠 分组背包
- 1190: [HNOI2007]梦幻岛宝珠 - BZOJ
- [BZOJ 1190][HNOI2007]梦幻岛宝珠
- BZOJ 1190: [HNOI2007]梦幻岛宝珠
- BZOJ 1190 [HNOI2007]梦幻岛宝珠
- bzoj1190 梦幻岛宝珠 动态规划
- [DP 背包] BZOJ 1190 [HNOI2007]梦幻岛宝珠
- 1190: [HNOI2007]梦幻岛宝珠
- 题解 P3188 【[HNOI2007]梦幻岛宝珠】 DP
- 【bzoj1187】[HNOI2007]神奇游乐园 插头dp
- BZOJ 1187 HNOI 2007 神奇游乐园 插头DP
- BZOJ 1187 HNOI2007 神奇游乐园 插头DP
- 【插头DP】BZOJ1187- [HNOI2007]神奇游乐园
- [bzoj1195][HNOI2006]最短母串_动态规划_状压dp