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

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/HowardEmily/article/details/77175117

题目链接


/*
	百度之星资格赛1004
	01背包套路题.这个题目是一个01背包+记录路径的题目.
	关于记录路径的套路题,一般开一个book标记一下,book[i][j]表示容量为j时放入了第i个物品.
	由于我们从前往后将物品装入背包并维护最大值,所以我们看背包中装入哪些物品时从后往前,
	因为前面的物品已经有一个价值了,如果后面的物品能放进去那么一定是使答案变得更优了,那么我们就
	从后往前遍历放入的物品,然后将它的价值减去一直往前,直到价值变为0.
	但是这个题目是存在价值为0的东西的,是一个坑点.!!!! 
	判断字典序最小的时候,我就是直接把所有放进的物品取出来,排个序然后比较字典序就好 
	 
*/



#include <stdio.h>  
#include <string.h>    
#include <iostream>    
#include <algorithm>
#define inf 0x7f7f7f7f
using 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;
}


展开阅读全文

没有更多推荐了,返回首页