百度之星资格赛 1004 度度熊的午饭时光(01背包+最小序号和+字典序+有bug)

分析
首先声明一下,我的代码有漏洞的,求大神给个正确代码
思路如下:
首先做一遍01背包记录路径并求出最大总分,令path[i][j]表示第i个物品包含在dp[j]的求值过程中.再逆序枚举money,如果dp[money]为最大总分,那么用c[num][j]保存物品并排序,并用mark记录序号最小并且字典序最小的那一个num,最后对c[mark][1]~c[mark][c[mark][0]]处理即可
trick
但是有一组数据很奇怪啊
5 4 1 1 2 2 3 3 4 4,应该输出5 5 1 4,但是我的程序输出5 5 2 3,然后我修改了if(dp[j]<dp[j-cost[i]]+score[i])if(dp[j]<=dp[j-cost[i]]+score[i]),输出对了,交上去wa了,求一个正确代码

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define F(i,a,b) for(int i=a;i<=b;++i)
#define R(i,a,b) for(int i=a;i<b;++i)
#define mem(a,b) memset(a,b,sizeof(a))

int t;
int money,n;
int cost[111],score[111];
int dp[1010];
int path[1010][1010];//path[i][j]表示第i个物品包含在dp[j]的求值过程中
int c[1010][1010];
int maxscore,maxsum;

int check(int num,int mark)
{
    int cnt1=c[num][0],cnt2=c[mark][0];
    for(int i=1,j=1;i<=cnt1&&j<=cnt2;++i,++j) if(c[num][i]!=c[mark][j]) return c[num][i]-c[mark][j];
        return 0;
}

int main()
{
    scanf("%d",&t);
    F(qq,1,t)
    {
        scanf("%d%d",&money,&n);
        F(i,1,n) scanf("%d %d",score+i,cost+i);
        mem(dp,0);mem(path,0);

        F(i,1,n)
        {
            for(int j=money;j>=cost[i];j--)
            {
                if(dp[j]<dp[j-cost[i]]+score[i]) 
                {
                    path[i][j]=1;
                    dp[j]=dp[j-cost[i]]+score[i];
                }
            }
        }
        maxscore=dp[money];
        int num=0,mark=0;
        maxsum=1e9;
        for(int j=money;j>=0;--j) if(dp[j]==maxscore)
        {
            int cnt=0,k=j,sum=0;//序号和
            for(int i=n;i>=1&&k>=0;i--) if(path[i][k])
            {
                c[num][++cnt]=i;
                k-=cost[i];
                sum+=i;
            }
            c[num][0]=cnt;
            sort(c[num]+1,c[num]+1+cnt);
            if(maxsum>sum)
            {
                maxsum=sum;
                mark=num;
            }
            else if((maxsum==sum)&&check(num,mark)<0)  mark=num;
            ++num;
        }
        int maxcost=0,cnt=c[mark][0];
        F(i,1,cnt) maxcost+=cost[c[mark][i]];
        printf("Case #%d:\n",qq );
        printf("%d %d\n",maxscore,maxcost );
        F(i,1,cnt) printf("%d%c",c[mark][i],i==cnt?'\n':' ' );
    }
    return 0;
}
posted @ 2017-08-06 21:52  遗风忘语  阅读(195)  评论(0编辑  收藏  举报