今天做的两道DP和我以前做的不同,以前没试过换个变量来当作背包的容量,前面一道题奠定了这题的基础,这道题一看见的时候就知道用支票的个数来当容量,这道题有点题意不清,没看discuss的时候我也把题意理解错了,它说单项物品不超过600元其实是此类物品不超过600元,这道题也不能完全按照Robberies来做,这里有金额q的限制.
转移方程为d[i]=max(d[j])+p[i]; 1=<j<i;
代码:
#include<iostream>
#include<cmath>
using namespace std;
double dp[35],p[35];
int main()
{
int n,flag,i,j,m;
double q,sum,temp,d[100];
char ch;
while( scanf("%lf%d",&q,&n)&&n){
j=1;
for( i=1; i<=n; i++){
scanf("%d",&m);
flag=1;
sum=0;
memset(d,0,sizeof(d));
while( m--){
scanf(" %c:%lf",&ch,&temp);
d[ch-'A']+=temp; //是同类物品的累计
if( ch!='A'&&ch!='B'&&ch!='C'||d[ch-'A']>600){
flag=0;
}
sum+=temp;
}
if( sum<=1000&&flag)
p[j++]=sum;
}
n=j-1;
memset(dp,0,sizeof(dp));
double ret=0;
for( i=1; i<=n; i++){
double mx=0.0;
for( j=1; j<i; j++)
if( dp[j]>mx&&dp[j]+p[i]<=q)
mx=dp[j];
dp[i]=mx+p[i];
if( ret<dp[i])
ret=dp[i];
}
printf("%.2lf\n",ret);
}
return 0;
}
或者把最后的关键代码改成比较普通的0/1背包就比较好理解了。
for( i=1; i<=n; i++){
for( j=n; j>0; j--){
temp=dp[j-1]+p[i];
if( temp<=q&&temp>dp[j])
dp[j]=temp;
}
}
本文探讨了一种在动态规划中使用支票个数作为背包容量的新颖方法,解决了一个金额限制条件下的物品选择问题。通过实例分析,解释了如何通过转移方程和代码实现这一解法,并对比了常规的0/1背包算法,提供了更直观的理解路径。
1539

被折叠的 条评论
为什么被折叠?



