zoukankan      html  css  js  c++  java
  • bzoj1190 梦幻岛宝珠

    题目链接:https://darkbzoj.tk/problem/1190

    显然不可能直接0/1背包
    考虑(wei = a * 2 ^ b)这个性质,于是可以按(b)分层转移,
    (f[i][j])表示只用(wei = a * 2 ^ i)的物品拼成重量为(j * 2 ^ i)的最大价值
    (f[i][j])即为普通的0/1背包
    考虑分层转移
    (g[i][j])表示只用(wei = a * 2 ^ k,(k = 1,2,ldots,i))的物品拼成重量为(j * 2 ^ i + (w的后i-1位))的最大价值
    (g[i][j])的转移方程为

    [g[i][j] = max(f[i][j-k] + g[i-1][min(1000,g[i-1][k*2 + w_{i-1}]),(k = 0,1,ldots,j) ]

    最终的答案即为(g[len][1])

    遗留问题:0/1背包,完全背包等的初值问题

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<stack>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 110;
    
    int n,m,cnt;
    ll v[maxn],w[maxn],c[maxn],vb[maxn][maxn],f[maxn][maxn*100],g[maxn][maxn*100];
    int wb[maxn][maxn];
    
    ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
    
    int main(){
    	while(1){
    		memset(c,0,sizeof(c));
    		memset(f,0,sizeof(f));
    		memset(g,0,sizeof(g)); 
    		 
    		n = read(), m = read(); cnt = 0;
    		if(n==-1 && m==-1) break;
    		
    		for(int i=1;i<=n;++i) w[i] = read(), v[i] = read();
    		
    		int W = m, num;
    		while(W > 0){ ++cnt; W >>= 1; }
    		
    		for(int i=1;i<=n;++i){
    			W = w[i], num = 0;
    			while(W % 2 == 0){ ++num; W /= 2; }
    			wb[num][++c[num]] = W, vb[num][c[num]] = v[i];
    		}
    		
    		for(int i=0;i<cnt;++i){
    			f[i][0] = 0;
    			for(int I=1;I<=c[i];++I){
    				for(int j=1000;j>=wb[i][I];--j){
    					if(f[i][j-wb[i][I]] != -1) f[i][j] = max(f[i][j], f[i][j-wb[i][I]] + vb[i][I]);
    				}
    			}
    		}
    		
    		for(int j=0;j<=1000;++j) g[0][j] = f[0][j];
    		for(int i=1;i<cnt;++i){
    			for(int j=0;j<=1000;++j){
    				for(int k=0;k<=j;++k){
    					if(((k<<1) + ((m>>(i-1)) & 1)) <= 1000) g[i][j] = max(g[i][j], f[i][j-k] + g[i-1][(k<<1) + ((m>>(i-1)) & 1)]);
    				}
    			}
    		}
    		
    		printf("%lld
    ",g[cnt-1][1]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    如何生成随机数
    2017新数组
    JAVA基础
    java基本数据类型
    简易图片自动轮播
    JDK,JRE,JVM
    年月日 日期选择问题
    多选按钮选中进行下一步
    js基本函数和基本方法
    数组简单应用
  • 原文地址:https://www.cnblogs.com/tuchen/p/13869333.html
Copyright © 2011-2022 走看看