题目大意
原题链接:HDOJ 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
解题思路
我本来想用贪心算法的,可是我写好算法,运行几遍试过了是ok的,只是不给AC,我想了好久,脑壳都快头秃了,才看到一个人的博客里的分析才理解为什么不能使用贪心算法。
#include<bits/stdc++.h>
using namespace std;
struct rice{
int p;
int h;
int c;
double rate;
}r[110];
bool cmp(rice a,rice b){
return a.rate<b.rate;
}
int main()
{
int C,n,m;
cin>>C;
while(C--){
cin>>n>>m; //n表示经费,m表示大米的种类
for(int i=1;i<=m;i++){
cin>>r[i].p>>r[i].h >>r[i].c ; // p每袋的价格;h每袋的重量;c对应种类大米的袋数
r[i].rate =(double)r[i].p/(double)r[i].h ;
}
sort(r,r+m+1,cmp);
double res=0;
for(int i=1;i<=m;i++)
{
if(r[i].p *r[i].c >=n){
res=res+r[i].h *(n/r[i].p)*1.0;
break;
}
else
{
res=res+r[i].c *r[i].h *1.0;
n=n-r[i].p *r[i].c *1.0;
}
}
cout<<res<<endl;
}
return 0;
}
我认为这个分析是正确的,所以就只能将完全背包转化为01背包问题解决。
代码实现
#include<bits/stdc++.h>
using namespace std;
int c[105],v[105],b[105];
int dp[105];
int main()
{
int n,m,t;
cin>>t;
while(t--){
cin>>n>>m;
for(int i=1;i<=m;i++)
cin>>c[i]>>v[i]>>b[i];
memset(dp,0,sizeof(dp));
for(int i=1 ;i<=m;i++)
for(int j=1;j<=b[i];j++)
for(int k=n;k>=c[i];k--)
{
dp[k]=max(dp[k],dp[k-c[i]]+v[i]);
}
cout<<dp[n]<<endl;
}
return 0;
}