您的位置:首页 > 其它

度度熊的午饭时光

2017-08-07 07:57 113 查看

题目描述

度度熊最期待每天的午饭时光,因为早饭菜品清淡,晚饭减肥不敢吃太多(胖纸的忧伤T.T)。

百度食堂的午餐超级丰富,祖国各大菜系应有尽有,度度熊在每个窗口都有爱吃的菜品,而且他还为喜爱的菜品打了分,吃货的情怀呀(>.<)。

但是,好吃的饭菜总是很贵,每天的午饭预算有限,请帮度度熊算一算,怎样打饭才能买到的最好吃的饭菜?(不超过预算、不重样、午餐等分最高的情况下,选择菜品序号加和最小,加和相等时字典序最小的组合)

题目分析

这一道题就是典型的背包DP。

我们可以设一下bz[i]这个布尔数组为是否能刚好用掉i元钱,然后用一个辅助布尔数组,bz2[i][j]表示在刚好花掉i元钱,最优方案的时候第j个菜是否会被选中。

接着我们便会得到一个转移方程。

如果bz[i-c[j]]的方案比bz[i]好,

bz2[i]=bz2[j]。

但问题是,我们怎么判断bz[i-c[j]]的方案是否会比bz[i]好呢?

首先我们先判断一下他们的分数(注意,bz[i-c[j]]的所有分数和加起来后还要加是s[j]!),如果分数相同,我们就看一下他们的编号和(也别忘了加j!)如果编号和相同,我们就看一下他们的字典序是否相等,哪个更小就选哪一个。

最后选择所有方案中最优的方案。

代码

#include<cstdio>
#include<cstring>
using namespace std;
bool bk[1100][110],bz[1100];
int s[1100],c[1100];
int b,n;
int sum7[110],sum8[110];
int ans3[110];
int mymin(int x,int y) {return x<y?x:y;}
void insert(int cost,int id)
{
if(bz[cost]==false)
{
bz[cost]=true;
for(int i=1;i<=n;i++)
{
bk[cost][i]=bk[cost-c[id]][i];
}
bk[cost][id]=true;
return ;
}
if(bk[cost-c[id]][id]==true)
{       return ;
}
int sum=0,sum2=0,sum3=0,sum4=0,sum5=0,sum6=0;
for(int i=1;i<=n;i++)
{
if(bk[cost-c[id]][i]==true)
{
sum+=i;
sum3+=s[i];
sum5++;
sum7[sum5]=i;
}
if(bk[cost][i]==true)
{
sum2+=i;
sum4+=s[i];
sum6++;
sum8[sum6]=i;
}
}
sum5++;
sum7[sum5]=id;
bool bk2=false;
if(sum+id<sum2) bk2=true;
if(sum+id==sum2)
{
bool bz2=false;
for(int i=1;i<=mymin(sum5,sum6);i++)
{
if(sum7[i]<sum8[i])
{
bz2=true;
bk2=true;
break;
}
if(sum7[i]>sum8[i])
{
bz2=true;
break;
}
}
if(bz2==true&&sum5>sum6)
{
bk2=true;
}
}
if(sum3+s[id]>sum4||(bk2==true&&sum3+s[id]==sum4))
{
for(int i=1;i<=n;i++)
{
bk[cost][i]=bk[cost-c[id]][i];
}
bk[cost][id]=true;
}
return ;
}
int main()
{
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
int t,t2=0;
scanf("%d",&t);
while(t--)
{
scanf("%d",&b);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&s[i],&c[i]);
}
memset(bz,false,sizeof(bz));
memset(bk,false,sizeof(bk));
bz[0]=true;
for(int i=1;i<=n;i++)
{
for(int j=b;j>=c[i];j--)
{
if(bz[j-c[i]]==true)
{
insert(j,i);
}
}
}
int ans=-1,ans2;
for(int i=0;i<=b;i++)
{
int sum9=0;
for(int j=1;j<=n;j++)
{
if(bk[i][j]==true)
{
sum9+=s[j];
}
}
bool bk2=false;
if(sum9==ans)
{
int sum=0,sum2=0,sum3=0,sum4=0,sum5=0,sum6=0;
for(int j=1;j<=n;j++)
{
if(bk[i][j]==true)
{
sum+=j;
sum3+=s[j];
sum5++;
sum7[sum5]=j;
}
if(bk[ans2][j]==true)
{
sum2+=j;
sum4+=s[j];
sum6++;
sum8[sum6]=j;
}
}
if(sum<sum2) bk2=true;
if(sum==sum2)
{
bool bz2=false;
for(int j=1;j<=mymin(sum5,sum6);j++)
{
if(sum7[j]<sum8[j])
{
bz2=true;
bk2=true;
break;
}
if(sum7[j]>sum8[j])
{
bz2=true;
break;
}
}
if(bz2==false&&sum5>sum6)
{
bk2=true;
}
}
}
if(sum9>ans||(sum9==ans&&bk2==true))
{
ans=sum9;
ans2=i;
}
}
printf("Case #%d:\n",++t2);
printf("%d %d\n",ans,ans2);
int len=0;
for(int i=1;i<=n;i++)
{
if(bk[ans2][i]==true)
{
len++;
ans3[len]=i;
}
}
for(int i=1;i<=len;i++)
{
if(i<len) printf("%d ",ans3[i]);
else printf("%d\n",ans3[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: