现在的位置: 首页 > 综合 > 正文

HDU1864之背包/搜索

2014年02月27日 ⁄ 综合 ⁄ 共 2502字 ⁄ 字号 评论关闭

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

抱歉!评论已关闭.