度度熊的午饭时光

来源:互联网 发布:日产空燃比传感器数据 编辑:程序博客网 时间:2024/05/17 03:48

题目描述

度度熊最期待每天的午饭时光,因为早饭菜品清淡,晚饭减肥不敢吃太多(胖纸的忧伤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;}
原创粉丝点击