百度之星资格赛1004 01背包+记录路径套路

来源:互联网 发布:剑灵人物数据 编辑:程序博客网 时间:2024/06/07 03:19

题目链接


/*百度之星资格赛100401背包套路题.这个题目是一个01背包+记录路径的题目.关于记录路径的套路题,一般开一个book标记一下,book[i][j]表示容量为j时放入了第i个物品.由于我们从前往后将物品装入背包并维护最大值,所以我们看背包中装入哪些物品时从后往前,因为前面的物品已经有一个价值了,如果后面的物品能放进去那么一定是使答案变得更优了,那么我们就从后往前遍历放入的物品,然后将它的价值减去一直往前,直到价值变为0.但是这个题目是存在价值为0的东西的,是一个坑点.!!!! 判断字典序最小的时候,我就是直接把所有放进的物品取出来,排个序然后比较字典序就好  */#include <stdio.h>  #include <string.h>    #include <iostream>    #include <algorithm>#define inf 0x7f7f7f7fusing namespace std;typedef long long ll;const int maxn = 1e3+10;int m,n;ll s[maxn],c[maxn],dp[maxn];int book[maxn][maxn];int num[maxn][maxn];int cmp(int x,int y){    for(int i=1,j=1;i<=num[x][0]&&j<=num[y][0];i++,j++)    {        if(num[x][i]!=num[y][j])        return num[x][i]-num[y][j];    }    return 0;}int main(){    int t;    cin>>t;    int ca =1;    while(t--)    {        memset(dp,0,sizeof (dp));        memset(book,0,sizeof (book));        memset(num,0,sizeof (book));        scanf("%d%d",&m,&n);        for(int i = 1;i <= n;i++)        scanf("%lld%lld",&s[i],&c[i]);         for(int i=1;i<=n;i++)         {             for(int j=m;j>=c[i];j--)             {                 if(dp[j]<dp[j-c[i]]+s[i])                 {                     dp[j]=dp[j-c[i]]+s[i];                     book[i][j]=1;                 }             }         }         ll index=inf;         ll maxx=0;         int cnt=0,item=0;         for(int i=0;i<=m;i++)         maxx=max(dp[i],maxx);         for(int i=m;i>=0;i--)         {             if(dp[i]==maxx)             {                 ll sum=0;                 int k=1;                 int j=n,w=i;                 while(j>=1&&w>=0)                 {                     if(book[j][w])                     { num[cnt][k++]=j;                         sum+=j;                         w-=c[j];                    }                    j--;                 }                 num[cnt][0]=k-1;                 sort(num[cnt]+1,num[cnt]+1+num[cnt][0]);                 if(index>sum)                 {                     index=sum;                     item=cnt;                 }                 else if(index==sum&&cmp(item,cnt)>0)                 {                     item=cnt;                 }                 cnt++;            }         }         ll money=0,score=0;         for(int i=1;i<=num[item][0];i++)         {             int w=num[item][i];             money+=c[w];             score+=s[w];         }         printf("Case #%d:\n",ca++);         printf("%lld %lld\n",score,money);         for(int i=1;i<=num[item][0];i++)         printf("%d%c",num[item][i],i==num[item][0]?'\n':' ');    }    return 0;}


阅读全文
0 0