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;
}