同一个部门的、同一所大学的、同一年出生的、使用同一种型号电脑的员工们总是以各种理由组织各种长期的、临时的饭团。
参加饭团,不仅可以以优惠的价格尝到更加丰富的菜式,还可以在吃饭的时候和同事们增进感情。
但是,随着百度的员工越来越多,各个饭团的管理变得繁杂起来。特别是为了照顾员工们越来越挑剔的胃,饭团的点菜负责人的压力也越来越大。现在,这个任务就交给“百度之星”了,因为,你将要为所有的百度饭团设计一个自动点菜的算法。
饭团点菜的需求如下:
1.经济是我们要考虑的一个因素,既要充分利用百度员工的午餐补助,又不能铺张浪费。因此,我们希望最后的人均费用越接近12元越好。
2.菜式丰富是我们要考虑的另一个因素。为简单起见,我们将各种菜肴的属性归结为荤菜,素菜,辛辣,清淡,并且每个菜只能点一次。
3.请谨记,百度饭团在各大餐馆享受8折优惠。
输入要求:
1.输入数据第一行包含三个整数N,M,K(0<N<=16,0<M<=N,0<K<=12),分别表示菜单上菜的数目,饭团需要点的菜的数目,就餐的人数;
2.紧接着N行,每行的格式如下:
菜名(长度不超过20个字符) 价格(原价,整数)是否荤菜(1表示是,0表示否) 是否辛辣(1表示是,0表示否);
3.第N+2行是 a b c d 四个整数,分别表示需要点的荤菜,素菜,辛辣,清淡菜的数目。例:
3 2 2
水煮鱼 30 1 1
口水鸡 18 1 1
清炖豆腐 12 0 0
1 1 1 1
样例:in.txt
输出要求:
对于每组测试数据,输出数据包含M+1行,前M行每行包含一个菜名(按菜名在原菜单的顺序排序)。第M+1行是人均消费,结果保留两位小数。例:
口水鸡
清炖豆腐
12.00
样例
// *************************************************************** // Main version: 1.0 · date: 10/02/2007
// -------------------------------------------------------------
// Write By
凌剑(Bujiwu)
// -------------------------------------------------------------
// Copyright (C) 2007 - All Rights Reserved
// ***************************************************************
//
// ***************************************************************
#include
<iostream>
#include
<string>
#include
<fstream>
#include
<math.h>
using
namespace std;
double
AverageMinus=0; //
人均消费与的偏移量
double
AverageCost=0; //
人均消费
bool
Flag=true; //
满足条件日第一次偏移量标志
//
菜单信息结构体
typedef
struct
{
string DishName; //
菜名
int Price; //价格 int MeatDish; //是否为晕菜 int NaDish; //是否为辛辣
}Dish;
//
点菜信息结构体
typedef
struct
{
int MenuTotal; //菜单上菜的数目 0<N<=16,<M<=N,<K<=12 int ReqCount; //饭团需要点的菜的数目 int PeopleCount; //就餐的人数 int MeatDishCount; //荤菜数目 int SuDishCount; //素菜数目 int NaDishCount; //辛辣菜数目 int DanDishCount; //清淡菜数目
}info;
//
判断结果是否满足点菜要求
void
JudgeResult(const info *SelectMenuInfo,Dish *SaveData,Dish *SaveDataResult)
{
int MeatTotal=0;
int NaTotal=0;
double TotalPrice=0;
for (int j=1; j<=SelectMenuInfo->ReqCount; j++)
{
MeatTotal +=SaveData[j].MeatDish; NaTotal +=SaveData[j].NaDish; TotalPrice +=SaveData[j].Price;
}
//
满足点菜要求即荤菜数目与辛辣菜数目吻合
if(SelectMenuInfo->MeatDishCount==MeatTotal&&SelectMenuInfo->NaDishCount==NaTotal)
{
double AverageCostCount=0;
double AverageMinusNow=0;//
此次的消费与偏移量
//
计算人均消费
AverageCostCount=(TotalPrice*0.8)/SelectMenuInfo->PeopleCount;
//
求出当次点菜人均消费偏移量
AverageMinusNow =abs(AverageCostCount-12);
//
如果消费偏移量比原来保存的小则更新
if(AverageMinusNow<AverageMinus||Flag)
{
//
保存最接近人均元消费的信息
Flag =false;
//
更新人均消费与的偏移量与人均消费
AverageCost =AverageCostCount; AverageMinus =AverageMinusNow; for (int j=1; j<=SelectMenuInfo->ReqCount; j++)
{
SaveDataResult[j]=SaveData[j];
}
}
}
}
//
运用回逆法点ReqCount道菜,然后用JudgeResult是否满足要求
void
GetDishes(int num, int pos,Dish *SaveData,const info *SelectMenuInfo,Dish *SaveDataResult,const Dish *SrcData)
{
if (num == SelectMenuInfo->ReqCount)//
处理最后一个菜
{
for (int i=pos; i<SelectMenuInfo->MenuTotal; i++)
{
SaveData[num] = SrcData[i];
//
判断结果是否满足要求
JudgeResult(SelectMenuInfo,SaveData,SaveDataResult);
}
}
else //
如果处理的不是最后一个菜,应采用回溯方法以取得最优解
{
for (int i=pos; i<SelectMenuInfo->MenuTotal-SelectMenuInfo->ReqCount+num; i++)
{
SaveData[num] = SrcData[i];
GetDishes(num+1, i+1,SaveData,SelectMenuInfo,SaveDataResult,SrcData);
}
}
}
/************************************************************************/
/*
从文件FilePath中读取菜单信息,将
/*
菜单上菜的数目、饭团需要点的菜的数目、就餐的人数、荤菜数目、素菜数目、
/*辛辣菜数目、清淡菜数目存入到SelectMenuInfo结构体中,将菜单信息通过DishMenu结构体返回 */
/************************************************************************/
Dish* ReadDataFromFile(const char *FilePath,info *SelectMenuInfo)
{
ifstream inFile("in.txt");
if(inFile==NULL)
{
cerr<<"
打开文件失败"
<<endl;
return NULL;
}
inFile>>SelectMenuInfo->MenuTotal>>SelectMenuInfo->ReqCount>>SelectMenuInfo->PeopleCount;
cout<<"
菜单上菜的数目:"
<<SelectMenuInfo->MenuTotal<<endl;
cout<<"
点的菜的数目:"
<<SelectMenuInfo->ReqCount<<endl;
cout<<"
就餐的人数:"
<<SelectMenuInfo->PeopleCount<<endl;
cout<<"++++++++++++++++++++++++++++++++"<<endl;
Dish *DishMenu =new Dish[SelectMenuInfo->MenuTotal+1]; //菜单信息
//
菜单信息
int nPos=0;
while(nPos<(SelectMenuInfo->MenuTotal))
{
inFile>>DishMenu[nPos].DishName;
inFile>>DishMenu[nPos].Price;
inFile>>DishMenu[nPos].MeatDish;
inFile>>DishMenu[nPos].NaDish;
cout<<DishMenu[nPos].DishName<<" "<<DishMenu[nPos].Price<<" "<<DishMenu[nPos].MeatDish<<" "<<DishMenu[nPos].NaDish<<endl;
nPos++;
}
//
读取点菜信息
inFile>>SelectMenuInfo->MeatDishCount;
inFile>>SelectMenuInfo->SuDishCount;
inFile>>SelectMenuInfo->NaDishCount;
inFile>>SelectMenuInfo->DanDishCount;
cout<<"++++++++++++++++++++++++++++++++"<<endl;
cout<<"
荤菜数目:"
<<SelectMenuInfo->MeatDishCount<<endl;
cout<<"
素菜数目:"
<<SelectMenuInfo->SuDishCount<<endl;
cout<<"
辛辣菜数目:"
<<SelectMenuInfo->NaDishCount<<endl;
cout<<"
清淡菜数目:"
<<SelectMenuInfo->DanDishCount<<endl;
inFile.close();
return DishMenu;
}
//
保存最后结果输出到文件DstFilePath
int SaveDataToFile(const char *DstFilePath,const info *SelectMenuInfo,const Dish* SaveDataResult)
{
ofstream outFile(DstFilePath);
if(outFile==NULL)
{
cerr<<"
创建文件失败"
<<endl;
return -1;
}
cout<<"++++++++++++++++++++++++++++++++"<<endl;
cout<<"
最后结果:"
<<endl;
for (int j=1; j<=SelectMenuInfo->ReqCount; j++)
{
cout<<"
菜名:"
<<SaveDataResult[j].DishName<<endl;
outFile<<SaveDataResult[j].DishName<<endl;
}
cout<<"
人均消费:"
<<AverageCost<<endl;
outFile<<AverageCost<<endl;
outFile.close();
return 0;
}
int
main(void)
{
info *SelectMenuInfo=new info;
char SrcFilePath[]="in.txt";
char DstFilePath[]="out.txt";
Dish *DishMenu=NULL;
DishMenu=ReadDataFromFile(SrcFilePath,SelectMenuInfo);
if(DishMenu==NULL)
{
cout<<"
获取文件信息失败"
<<endl;
return -1;
}
Dish *SaveDataResult=new Dish[SelectMenuInfo->ReqCount+1]; //最后点菜信息结果 Dish *SaveData =new Dish[SelectMenuInfo->ReqCount+1]; //保存回逆过程中的点菜信息
GetDishes(1,0,SaveData,SelectMenuInfo,SaveDataResult,DishMenu);
int ret =SaveDataToFile(DstFilePath,SelectMenuInfo,SaveDataResult);
if(ret!=0)
{
cout<<"
保存文件信息失败"
<<endl;
return -1;
}
delete SelectMenuInfo;
delete[] SaveDataResult;
delete[] SaveData;
system("pause");
return 0;
}
|
#include
<iostream>
#include
<string>
#include
<fstream>
#include
<math.h>
using
namespace std;
int MenuTotal=0; //菜单上菜的数目 0<N<=16,<M<=N,<K<=12
int
ReqCount=0; //
饭团需要点的菜的数目
int
PeopleCount=0; //
就餐的人数
int
MeatDishCount=0; //
荤菜数目
int
SuDishCount=0; //
素菜数目
int
NaDishCount=0; //
辛辣菜数目
int
DanDishCount=0; //
清淡菜数目
double
AverageMinus=0; //
人均消费与的偏移量
double
AverageCost=0; //
人均消费
bool
Flag=true; //
满足条件日第一次偏移量标志
typedef
struct
{
string DishName; //
菜名
int Price; //价格 int MeatDish; //是否为晕菜 int NaDish; //是否为辛辣
}Dish,*pDish;
void GetDishes(int num, int pos,Dish *SaveData,Dish *SaveDataResult,const Dish *SrcData)
{
if (num == ReqCount)//
处理最后一个菜
{
for (int i=pos; i<MenuTotal; i++)
{
SaveData[num] = SrcData[i];
int MeatTotal=0; int NaTotal=0; double TotalPrice=0; for (int j=1; j<=ReqCount; j++)
{
MeatTotal +=SaveData[j].MeatDish; NaTotal +=SaveData[j].NaDish; TotalPrice +=SaveData[j].Price;
}
//
满足点菜要求即荤菜数目与辛辣菜数目吻合
if(MeatDishCount==MeatTotal&&NaDishCount==NaTotal)
{
double AverageCostCount=0; double AverageMinusNow=0;//此次的消费与偏移量
//
计算人均消费
AverageCostCount=(TotalPrice*0.8)/PeopleCount;
//
人均消费偏移量
AverageMinusNow =abs(AverageCostCount-12);
//
如果消费偏移量比原来保存的小则更新
if(AverageMinusNow<AverageMinus||Flag)
{
//
保存最接近人均元消费的信息
Flag =false;
//
更新人均消费与的偏移量与人均消费
AverageCost =AverageCostCount; AverageMinus =AverageMinusNow; for (int j=1; j<=ReqCount; j++)
{
SaveDataResult[j]=SaveData[j];
}
}
}
}
}
else //
如果处理的不是最后一个菜,应采用回溯方法以取得最优解
{
for (int i=pos; i<MenuTotal-ReqCount+num; i++)
{
SaveData[num] = SrcData[i];
GetDishes(num+1, i+1,SaveData,SaveDataResult,SrcData);
}
}
}
int
main(void)
{
ifstream inFile("in.txt");
ofstream outFile("out.txt");
if(inFile==NULL)
{
cerr<<"
打开文件失败"
<<endl;
return -1;
}
if(outFile==NULL)
{
cerr<<"
创建文件失败"
<<endl;
return -1;
}
inFile>>MenuTotal>>ReqCount>>PeopleCount;
cout<<"
菜单上菜的数目:"
<<MenuTotal<<endl;
cout<<"
点的菜的数目:"
<<ReqCount<<endl;
cout<<"
就餐的人数:"
<<PeopleCount<<endl;
cout<<"++++++++++++++++++++++++++++++++"<<endl;
Dish *DishMenu =new Dish[MenuTotal+1]; //
菜单信息
Dish *SaveData =new Dish[ReqCount+1]; //
点菜信息
Dish *SaveDataResult=new Dish[ReqCount+1]; //最后点菜信息结果
int nPos=0;
while(nPos<MenuTotal)
{
inFile>>(DishMenu[nPos].DishName)>>(DishMenu[nPos].Price)>>(DishMenu[nPos].MeatDish)>>(DishMenu[nPos].NaDish);
cout<<DishMenu[nPos].DishName<<" "<<DishMenu[nPos].Price<<" "<<DishMenu[nPos].MeatDish<<" "<<DishMenu[nPos].NaDish<<endl;
nPos++;
}
//
读取点菜信息
inFile>>MeatDishCount>>SuDishCount>>NaDishCount>>DanDishCount;
cout<<"++++++++++++++++++++++++++++++++"<<endl;
cout<<"
荤菜数目:"
<<MeatDishCount<<endl;
cout<<"
素菜数目:"
<<SuDishCount<<endl;
cout<<"
辛辣菜数目:"
<<NaDishCount<<endl;
cout<<"
清淡菜数目:"
<<DanDishCount<<endl;
inFile.close();
GetDishes(1,0,SaveData,SaveDataResult,DishMenu);
cout<<"++++++++++++++++++++++++++++++++"<<endl;
cout<<"
最后结果:"
<<endl;
for (int j=1; j<=ReqCount; j++)
{
cout<<"
菜名:"
<<SaveDataResult[j].DishName<<endl;
outFile<<SaveDataResult[j].DishName<<endl;
}
cout<<"
人均消费:"
<<AverageCost<<endl;
outFile<<AverageCost<<endl;
outFile.close();
system("pause");
return 0;
}
|