zoukankan      html  css  js  c++  java
  • 金明的预算方案

    Description

    金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间金明自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早,金明就开始做预算了,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的。

    如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有0个、1个或2个附件。附件不再有从属于自己的附件。金明想买的东西很多,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为5等:用整数1~5表示,第5等最重要。他还从因特网上查到了每件物品的价格(都是10元的整数倍)。他希望在不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的总和最大。

    Analysis

    第一次遇到的依赖性背包问题。

    如果取消附件的限制,那么这题可以用01背包解决。加上附件之后,相当于1个主件变成了4件物品(附件的选择导致),且此4件物品互相冲突。因为4常数非常小..所以在计算到此主件组时,只要枚举4种情况,找出最优情况就行了。

    但是如果附件变多了,组合数太多,为2^n,该怎么办呢?不难发现主件组中各种组合进行了多次冗余计算,可以想到先给主件组中的组合来一发01背包,求出各种价格下的最大获得值,这样就把所有的组合化成了价格数个物品。当然这题无需优化。

    Code

    #include <bits/stdc++.h>
    
    int n,m,dp[32001],id[101];
    std::vector <int> gift[101];
    
    struct node{
    	int v,w;
    }th[101];
    
    int main(){
    	freopen("budget.in","r",stdin);
    	freopen("budget.ans","w",stdout);
    	std::cin>>n>>m;
    	for(int i=1;i<=m;i++){
    		int q;
    		std::cin>>th[i].v>>th[i].w>>q;
    		th[i].w*=th[i].v;
    		if(!q)id[++id[0]]=i;
    		else gift[q].push_back(i);
    	}
    	m=id[0];
    	for(int i=1;i<=m;i++)
    		for(int j=n;j>=th[id[i]].v;j--){
    			int v=th[id[i]].v;
    			int w=th[id[i]].w;
    			dp[j]=std::max(dp[j],dp[j-v]+w);
    			if(gift[id[i]].empty())continue;
    			for(int k=0;k<gift[id[i]].size();k++){
    				int s=gift[id[i]][k];
    				if(j>=th[s].v+v)
    					dp[j]=std::max(dp[j],dp[j-v-th[s].v]+w+th[s].w);
    			}
    			if(gift[id[i]].size()>1){
    				int s0=gift[id[i]][0];
    				int s1=gift[id[i]][1];
    				if(j>=th[s0].v+th[s1].v+v)
    					dp[j]=std::max(dp[j],dp[j-v-th[s0].v-th[s1].v]+w+th[s0].w+th[s1].w);
    			}
    		}
    	std::cout<<dp[n]<<std::endl;
    	return 0;
    }
    
  • 相关阅读:
    centOS7 查看防火墙状态 开放端口
    PHP之Trait详解 转
    ps 树形显示
    composer 打印美化
    第一章 Java Web应用开发技术
    团队博客20
    团队博客19
    团队博客18
    团队博客17
    团队博客16
  • 原文地址:https://www.cnblogs.com/qswx/p/9492515.html
Copyright © 2011-2022 走看看