http://acm.hdu.edu.cn/showproblem.php?pid=1864
此题用背包做并且是以票数作为背包,杭电能过,但蛮多数据是不符合的。
比如这些数据:
100.00 5
1 A:5
1 B:20
1 C:24
1 A:30
1 A:60
得到的是 90.00 但正确的应该是95.00
100.00 4
1 A:80
1 B:30
1 C:30
1 A:30
得到的是 80.00 但正确的应该是90.00
之所以会错就不多说了,相信能很容易想到。
还有一种是用Q*100作为背包,但是考虑到Q*100可能会很大,可能会超时超内存,虽然杭电上能过,但是换一题或许就没那么好运了,所以不推荐这么做.
以下是以票数作为背包的代码(杭电能过)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<iomanip> #define INF 99999999 using namespace std; const int MAX=31; double dp[MAX],value[MAX];//dp是选i张票获得的最大报销,value是能够报销的票的价值. int main(){ double Q,b; int n,m; char a,c; while(cin>>Q>>n,n){ int k=0; for(int i=0;i<n;++i){ cin>>m; double money_A=0,money_B=0,money_C=0; bool flag=true; for(int j=0;j<m;++j){ cin>>a>>c>>b; if(a == 'A')money_A+=b; else if(a == 'B')money_B+=b; else if(a == 'C')money_C+=b; else flag=false; } if(money_A+money_B+money_C>Q || money_A+money_B+money_C>1000.0)flag=false; if(money_A<=600.0 && money_B<=600.0 && money_C<=600.0 && flag){ value[k++]=money_A+money_B+money_C; } } for(int i=1;i<=k;++i)dp[i]=0; double max_money=0; for(int i=0;i<k;++i){ for(int j=k;j>=1;--j){ if(value[i]+dp[j-1]>dp[j] && value[i]+dp[j-1]<=Q){ dp[j]=value[i]+dp[j-1]; max_money=max(max_money,dp[j]); } } } cout<<fixed<<setprecision(2)<<max_money<<endl; } return 0; }
下面是用搜索做的,没找到什么错误数据。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<iomanip> #define INF 99999999 using namespace std; const int MAX=31; double value[MAX],max_money,Q; int k; void DFS(int i,double now_money,double s_money){//now_money表示目前报销的钱,s_money表示后面发票剩余的总钱数. if(i>=k){max_money=max(max_money,now_money);return;} //是否报销第i张发票. if(now_money+value[i]<=Q/*&& now_money+s_money>max_money*/){//now_money+s_money>max_money,不需要这个剪枝,因为在前面剪枝递归时就一定会满足这个条件. DFS(i+1,now_money+value[i],s_money-value[i]); } if(/*now_money<=Q&&*/now_money+s_money-value[i]>max_money){//now_money<=Q,不需要这个剪枝,因为在前面剪枝递归时就一定会满足这个条件. DFS(i+1,now_money,s_money-value[i]); } return; } int main(){ double b; int n,m; char a,c; while(cin>>Q>>n,n){ k=0; for(int i=0;i<n;++i){ cin>>m; double money_A=0,money_B=0,money_C=0; bool flag=true; for(int j=0;j<m;++j){ cin>>a>>c>>b; if(a == 'A')money_A+=b; else if(a == 'B')money_B+=b; else if(a == 'C')money_C+=b; else flag=false; } if(money_A+money_B+money_C>Q || money_A+money_B+money_C>1000.0)flag=false; if(money_A<=600.0 && money_B<=600.0 && money_C<=600.0 && flag){ value[k++]=money_A+money_B+money_C; } } double sum_money=0; for(int i=0;i<k;++i)sum_money+=value[i]; max_money=0; DFS(0,0,sum_money); cout<<fixed<<setprecision(2)<<max_money<<endl; } return 0; }