回想起以前似是而非做的题,现在有必要耐下性子,总结一下!
要投入热情了。
题意:
有m组药,给出采这个药的时间time 和 这个药的价值value。
(题外意:每个药只有一个)问在给分定时间t内如何采药可以达到最大价值。
即求规划m组药中的一个子集,使在t时间内,所取子集的价值和最大。
分析:
归类:0-1背包问题。即根据背包的大小,一个物品只能为放入(1) ,和不放入(0),两种状态。
状态:s( i , j ) 表示 前 i 组药,在时间 j 时的最大价值。
0 =< i < m 0 =< j <=t
1.如果 time_i 大于 j ,则 s( i ,j) = s(i - 1 , j)
2.如果time_i 小于等于 j,
若不包含第 i 株 ,其价值为 s(i -1 , j)
若包含第 i 株, 其价值为 s(i - 1 ,j - time_i) + value_i
s(i ,j)选上述较大者。
公式:
一个实例:
该实例截图转自:http://blog.sina.com.cn/s/blog_611253210100dw6b.html
#include<stdio.h>
#include<cstring>
int t , m ;
//甚至可以不用保存输入
//保存所有路径的算法
int s[101][1005];
int main (){
scanf( "%d%d" , &t , &m );
int i,j;
int time,val;
memset(s , 0 , sizeof(s));
for( i=1 ;i<=m ; i++ ){
scanf("%d%d" , &time , &val);
for( j = 0 ; j <= t ; j++){
if( time > j )s[i][j] = s[i-1][j] ;
else{
if(val + s[i-1][j-time] > s[i-1][j])
s[i][j] = val + s[i-1][j-time];
else s[i][j] = s[i-1][j];
}
}
}
printf("%d\n",s[m][t]);
}
#include<stdio.h>
#include<cstring>
int t , m ;
//使用一个数组保存
//但每次更新需从顶端开始,因为需要用低位数据
int s[1001];
int main (){
scanf( "%d%d" , &t , &m );
memset( s , 0 , sizeof(s) );
int time , val;
for( int i = 0 ; i < m ; i++ ){
scanf( "%d%d" , &time , &val );
for( int j = t ; j >= time ; j--){ //注意下界
if( s[j-time] + val > s[j])
s[j] = s[j-time] + val;
}
}
printf("%d\n",s[t]);
}