2006年百度之星程序设计大赛初赛题目1:饭团的烦恼

饭团的烦恼

同一个部门的,同一间大学的,同一年出生的,用同一种型号电脑的,员工们总是以各种理由,各种借口组织各种长久的,临时的饭团。

参加饭团,不仅可以以优惠的价格尝到更加丰富的菜式,还可以在吃饭的时候和同事们唠唠嗑,吹吹水,增进感情。

但是,随着百度的员工越来越多,各个饭团的管理随即变得烦杂。特别是为了照顾员工们越来越挑剔的胃口,饭团的点菜负责人背负的责任越来越大。现在,这个重担落在百度之星的肩上,因为,你们将要为所有的百度饭团设计一个自动点菜的算法。

饭团点菜的需求如下:

1.  经济是我们要考虑的一个因素,既要充分利用百度员工的午餐补助,又不能铺张浪费。因此,我们希望最后的人均费用越接近12元越好。

2.  菜式丰富是我们要考虑的另一个因素。为简单起见,我们将各种菜肴的属性归结为荤菜,素菜,辛辣,清淡,并且每个菜只能点一次。

3.  请紧记,百度饭团在各大餐馆享受8折优惠。

输入数据描述如下:

第一行包含三个整数NMK0<N<=160<M<=N0<K<=12),分别表示菜单上菜的数目,饭团需要点的菜的数目,就餐的人数。

紧接着N行,每行的格式如下:

菜名(长度不超过20个字符) 价格(原价,整数) 是否荤菜(1表示是,0表示否) 是否辛辣(1表示是,0表示否)

例:

水煮鱼 30  1  1

紧接着是a b c d 四个整数,分别表示需要点的荤菜,素菜,辛辣,清淡菜的数目。

输出数据:

对于每一测试数据,输出数据包含M+1行,前M行每行包含一个菜名(按菜名在原菜单的顺序排序)。第M+1行是人均消费,结果保留两位小数。

说明:

1.结果菜单的数目应该恰好为M,荤菜,素菜,辛辣,清淡菜的数目恰好为abcd。在满足这样的前提下,选择人均消费最接近12元的点菜方案。题目数据保证有且仅有一个解。

2.每组测试数据的结果用一个空行隔开。末尾不要有多余的空行。

输入样例

3 2 2

水煮鱼 30  1  1

口水鸡 18 1 1

清炖豆腐 12 0 0

1 1 1 1

输出样例

口水鸡

清炖豆腐

12.00

时间要求:1S之内



思路:深搜

#include <iostream>
#include <string>
#include<iomanip>
using namespace std;

int N,M,K,a,b,c,d,ca,cb,cc,cd,ordered_count;
float mindiff,bestmoney,difference;
//菜单上菜的数目,饭团需要点的菜的数目,就餐的人数,荤菜,素菜,辛辣,清淡菜
bool isordered[16],best[16];


struct dish
{
	string name;
	int price;
	int hun;
	int su;
	int la;
	int qing;
}mydish[16];

void dfs(int index)
{
	if(index>=N){
		if(ordered_count==M&&ca==a&&cb==b&&cc==c&&cd==d)
		{
			int money=0;
			for(int i=0;i<N;i++)
			{
				if(isordered[i])
					money+=mydish[i].price;
			}
			float currentdiff=money*0.8-K*12>0?money*0.8-K*12:K*12-money*0.8;
			if(currentdiff<mindiff) {
				mindiff=currentdiff;
				bestmoney=money*0.8;
				for(int i=0;i<N;i++)
					best[i]=isordered[i];
			}
			
		}
		return;
	}
	if(index<N&&ca+mydish[index].hun<=a&&cb+mydish[index].su<=b&&cc+mydish[index].la<=c&&cd+mydish[index].qing<=d&&ordered_count<=M)
	{
		isordered[index]=true;
		ordered_count++;
		ca+=mydish[index].hun;
		cb+=mydish[index].su;
		cc+=mydish[index].la;
		cd+=mydish[index].qing;
		dfs(index+1);
		ordered_count--;
		ca-=mydish[index].hun;
		cb-=mydish[index].su;
		cc-=mydish[index].la;
		cd-=mydish[index].qing;
		isordered[index]=false;
	}
		dfs(index+1);
}

int main(){
	//freopen("template.txt","r",stdin);
	cin>>N>>M>>K;
	mindiff=INT_MAX;
	for(int i=0;i<N;i++){
		cin>>mydish[i].name>>mydish[i].price>>mydish[i].hun>>mydish[i].la;
		mydish[i].su=1-mydish[i].hun;
		mydish[i].qing=1-mydish[i].la;
	}
	cin>>a>>b>>c>>d;
	dfs(0);
	for(int i=0;i<N;i++){
		if(best[i])
			cout<<mydish[i].name<<endl;
	}
	cout<<setprecision(2)<<fixed<<float(bestmoney/K)<<endl;
	return 0;
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值