| Time Limit: 1000MS | Memory Limit: 10000K | |||
| Total Submissions: 1145 | Accepted: 452 | Special Judge | ||
Description
Input
Output
Sample Input
12 9 4 5 2 8 5 100 120 5 21 32 110 54 3 0 0
Sample Output
3 1 2 4 Impossible to distribute
题意:
给m块A巧克力,l块B巧克力,要把这些巧克力装进一些小包,要保证每个小包只有一种类型的巧克力,输出装A巧克力的小包的总和序号。
题解:
只处理A巧克力就行了,当A放在包里的最多时,B能把包放满,那么就可行,这样就变成裸的01背包了。
不让输出方案倒很容易想到,让输出方案要怎么解决呢?想了好久,还是看了别人的思路,用一个数组pre[i]存dp[i]最大时最后放到dp[i]中的小包序号,然后再dfs找dp[m]的所有放置序列,由于让从小到大输出小包的序号,可以用个vis数组记录最后的序号。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1000+100;
int a[maxn],dp[maxn],pre[maxn];
bool vis[maxn];
int n,m,l;
void dfs(int x)
{
if(x==0)
return;
vis[pre[x]]=1;
dfs(x-a[pre[x]]);
}
int main()
{
while(~scanf("%d%d",&m,&l)&&l+m)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
for(int j=m;j>=a[i];j--)
{
if(dp[j]<dp[j-a[i]]+a[i])
{
dp[j]=dp[j-a[i]]+a[i];
pre[j]=i;
}
}
}
int ans=n;
dfs(dp[m]);
int sum=0;
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
ans--;
sum+=a[i];
}
}
if(sum<=l)
{
printf("%d",ans);
for(int i=1;i<=n;i++)
{
if(vis[i])
printf(" %d",i);
}
printf("\n");
}
else
{
printf("Impossible to distribute\n");
}
}
return 0;
}
原文:http://blog.csdn.net/caduca/article/details/43445569