百度之星资格赛1004 01背包+记录路径套路
2017-08-15 01:36
337 查看
题目链接
/*
百度之星资格赛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;
}
/*
百度之星资格赛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;
}
相关文章推荐
- 2017百度之星资格赛:1004. 度度熊的午饭时光(01背包+记录路径)
- 2017百度之星资格赛 1002-图 1003-DP 1004-01背包(解选择方案)
- hdu6083 2017"百度之星"资格赛1004 度度熊的午饭时光(背包dp+记录路径)
- 2017百度之星资格赛 1004 度度熊的午饭时光(01背包)
- hdu2126Buy the souvenirs (01背包+记录路径的种数)
- 度度熊的午饭时光[2017百度之星资格赛 1004]
- HDU 6083 度度熊的午饭时光(01背包+记录路径)
- CD - UVa 624 01背包记录路径
- 放盘子(百度之星资格赛1004)
- 2016"百度之星" - 资格赛(Astar Round1) 1004
- 2016"百度之星" - 资格赛(Astar Round1) 1004()
- ZOJ 3703 Happy Programming Contest 01背包+记录路径
- 百度之星资格赛 1004 Labyrinth
- 新年趣事之打牌(01背包+记录路径)
- UVA 624 CD(01背包+记录路径)
- 百度之星2014资格赛 1004 - Labyrinth
- 2014百度之星资格赛1004 度度熊走迷宫 Labyrinth
- “百度之星”资格赛 1004 度度熊与邪恶大魔王
- UVA - 624 (01背包,记录路径)
- 百度之星程序设计竞赛资格赛:1004放盘子