关闭

2006百度之星设计大赛-------(饭团的烦恼)

标签: 百度iostreammath.hnullstringdelete
920人阅读 评论(0) 收藏 举报
分类:
午餐饭团是百度内部参与人数最多的民间组织。

同一个部门的、同一所大学的、同一年出生的、使用同一种型号电脑的员工们总是以各种理由组织各种长期的、临时的饭团。

参加饭团,不仅可以以优惠的价格尝到更加丰富的菜式,还可以在吃饭的时候和同事们增进感情。
但是,随着百度的员工越来越多,各个饭团的管理变得繁杂起来。特别是为了照顾员工们越来越挑剔的胃,饭团的点菜负责人的压力也越来越大。现在,这个任务就交给百度之星了,因为,你将要为所有的百度饭团设计一个自动点菜的算法。

饭团点菜的需求如下:
1
.经济是我们要考虑的一个因素,既要充分利用百度员工的午餐补助,又不能铺张浪费。因此,我们希望最后的人均费用越接近12元越好。
2
.菜式丰富是我们要考虑的另一个因素。为简单起见,我们将各种菜肴的属性归结为荤菜,素菜,辛辣,清淡,并且每个菜只能点一次。
3
.请谨记,
百度饭团在各大餐馆享受8折优惠

输入要求:
1
.输入数据第一行包含三个整数NMK(0<N<=160<M<=N0<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结构体返回                                                                   */

/************************************************************************/

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

 输出结果:
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:27743次
    • 积分:473
    • 等级:
    • 排名:千里之外
    • 原创:19篇
    • 转载:2篇
    • 译文:0篇
    • 评论:8条
    文章存档
    最新评论