您的位置:首页 > 其它

NOI2006:金明的预算方案

2012-04-06 15:18 239 查看
题目链接:http://www.rqnoj.cn/Status_Show.asp?SID=744089

这题纠结了两三天,主要是主件与附件之间的关系,然后选择问题让人纠结。我们可以将主件与对应的附件进行分组,对每个分组,我们有如下几种选择方式,都不选,只选主件,选主件与一个附件,选主件与多个附件,根据题意,每个分组最多有四种情况,这里可以直接枚举,这几种选择是互不相容的,这样就转化为了分组背包问题。那么接下来编程就相对容易的多了。

分组背包的动规方程:f(k ,v) = max{ f(k-1 ,v) , f(k-1 , v -c[i]) + w[i] , 物品i属于组k} ,其中f(k ,v)表示背包容量为v,从前k中选择若干件物品获得最大值。其实这个题目直接是有依赖的背包问题,一般先转化成对应的组,变成分组背包问题,对于每个组可以进行一次01背包问题。

代码如下:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <deque>
#include <stdlib.h>
using namespace std ;

const int maxn = 3205 ;

struct Node
{
int p ;
int c ;
int w ;
int in ;
};

int dp[65][maxn] ;
deque<Node> v1[65];
Node pack_node[65][65] ;

int m ;
int n ;
int num ;

void input();
void work() ;
void init() ;

int main()
{
work()   ;
return 0 ;
}

void work()
{

int i ;
int v ;
int k ;

for(i = 0 ; i < 65 ; i ++)
v1[i].clear() ;

memset(dp , 0 , sizeof(dp)) ;
memset(pack_node , 0 ,sizeof(pack_node)) ;

//freopen("data.in" , "r" , stdin) ;

input() ;
init() ;

for(i = 1 ; i <= num ; i ++)
{
for( v = m ; v >= 0 ; v--)
{
dp[i][v] = dp[i-1][v] ;

for(k = 0 ; v >= pack_node[i][k].c && k < 4 ; k ++)
{
if(dp[i][v] < dp[i-1][v - pack_node[i][k].c] + pack_node[i][k].w)
{
dp[i][v] = dp[i-1][v - pack_node[i][k].c] + pack_node[i][k].w ;
}
}
}
}

printf("%d\n" , dp[num][m] * 10) ;
}
void  input()
{
int i ;
int j ;
Node a ;

scanf("%d%d" , &m , &n) ;
m = m / 10 ;
num = 0 ;

for(i = 1 ; i <= n ; i ++)
{
scanf("%d%d%d" ,&a.c , &a.w , &a.p ) ;
a.in  = i ;

a.c = a.c / 10 ;

if(a.p==0)
v1[++num].push_front(a) ;

else
{
for( j = 1 ; j <=num ; j ++)
if(v1[j][0].in == a.p)
break ;

v1[j].push_back(a) ;
}
}
}

void init()
{
int i ;
int len ;
for(i = 1 ; i <= num ; i ++)
{
len = v1[i].size() ;

if(len>=1)
{
pack_node[i][0].c = v1[i][0].c ;
pack_node[i][0].w = v1[i][0].c * v1[i][0].w ;

}
if(len>=2)
{
pack_node[i][1].c = pack_node[i][0].c + v1[i][1].c ;
pack_node[i][1].w = pack_node[i][0].w + v1[i][1].c * v1[i][1].w ;
}

if(len==3)
{
pack_node[i][2].c = pack_node[i][0].c + v1[i][2].c ;
pack_node[i][2].w = pack_node[i][0].w + v1[i][2].c * v1[i][2].w ;
pack_node[i][3].c = pack_node[i][1].c + v1[i][2].c ;
pack_node[i][3].w = pack_node[i][1].w + v1[i][2].c * v1[i][2].w ;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: