zoukankan      html  css  js  c++  java
  • 百度之星资格赛 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:
    ",qq );
            printf("%d %d
    ",maxscore,maxcost );
            F(i,1,cnt) printf("%d%c",c[mark][i],i==cnt?'
    ':' ' );
        }
        return 0;
    }
    
  • 相关阅读:
    SQL里面的函数应用
    Split的小用法
    堆栈和堆问题
    break,continue,goto,Return几个方法
    接口笔记
    抽象类
    虚方法
    将博客搬至CSDN
    运行数据区
    美团-走迷宫
  • 原文地址:https://www.cnblogs.com/chendl111/p/7296160.html
Copyright © 2011-2022 走看看