P3188 [HNOI2007]梦幻岛宝珠

链接

(b) 分组 (dp),最后合并时:

f[i][j]=max(f[i][j],f[i][j-k]+f[i-1][min(w[i-1],k<<1|(m>>i-1&1))]);

表示容量为 (j cdot 2^i + (m) & (2^i-1)),分 (j-k) 个给 (i) 组,分 (2k) 个给 (i-1) 组的最大价值。

#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define pb push_back
using namespace std;
const int N=35,M=1e3+10;
struct hh{
  int cos,val;
};
int n,m,f[N][M],w[N];
vector<hh>a[N];
IL int in(){
  char c;int f=1;
  while((c=getchar())<'0'||c>'9')
    if(c=='-') f=-1;
  int x=c-'0';
  while((c=getchar())>='0'&&c<='9')
    x=x*10+c-'0';
  return x*f;
}
int main()
{
	int x,y,len;
	while(n=in(),m=in(),~n){
		memset(f,0,sizeof(f));
		memset(w,0,sizeof(w));
		for(int i=0;i<=30;++i) a[i].clear();
		for(int i=1;i<=n;++i){
		  x=in(),y=in(),len=0;
		  while(~x&1) x>>=1,++len;
		  a[len].pb((hh){x,y}),w[len]+=x;
		}
		len=0;while((m>>len)^1) ++len;
		for(int i=0;i<=len;++i)
		  for(int k=0;k<a[i].size();++k)
		    for(int j=w[i];j>=a[i][k].cos;--j)
		        f[i][j]=max(f[i][j],f[i][j-a[i][k].cos]+a[i][k].val);
		for(int i=1;i<=len;++i){
		  w[i]+=w[i-1]+1>>1;
		  for(int j=w[i];~j;--j)
		    for(int k=0;k<=j;++k)
		      f[i][j]=max(f[i][j],f[i][j-k]+f[i-1][min(w[i-1],k<<1|(m>>i-1&1))]);
		}
		printf("%d
",f[len][1]);
	}
  return 0;
}
原文地址:https://www.cnblogs.com/yiqiAtiya/p/14001759.html