poj 1293 Duty Free Shop

Duty Free Shop
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 1145 Accepted: 452 Special Judge

Description

Pedro travelled to Europe to take part in the International Olympiad in Informatics and is coming back home. Since all his friends asked him to bring them some gift, he bought two big bags of chocolates (one of Mindt and one of Lilka). Each of these two bags contains a certain number of small chocolates. Buying those two bags was much less expensive than buying smaller, individual boxes of chocolates. At home, Pedro has some empty chocolate boxes that he kept from other trips. Pedro intends to distribute the chocolates he just bought into these smaller boxes, to give them to his friends. 
As soon as Pedro begins filling the small boxes, he realizes he has a big problem: since he has two different brands of chocolates, if he mixes chocolates of different brands into one small box, the friend who receives this small box will discover Pedro's trick to save money, and will not be pleased with him. 
You must help poor Pedro distribute the chocolates into the small boxes in such a way that every small box is completely full, and contains only one brand of chocolates. A number of chocolates may however be left unassigned to any box (Pedro will keep these chocolates to himself).

Input

The input contains several instances of the problem. Each instance consists of three lines. The first line contains two integers M and L that indicate respectively the number of chocolates Mindt and Lilka Pedro bought (0 <= M, L <= 1000). The next line contains an integer N representing the number of small boxes Pedro has (N <= M+L). The third line contains N integers indicating the capacity Ci > 0 of box number i (that is, the number of chocolates needed to fill that box). The end of input is indicated by M = L = 0.

Output

For each instance of the input your program must produce one line of output. If it is possible to distribute the chocolates as defined in the problem statement, print the number of boxes to be filled with Mindt chocolate, followed by a space, followed by the list of box numbers, in ascending order. Each box number in the list should be followed by a space. If it is impossible to distribute the chocolates,print "Impossible to distribute". If more than one solution exists, print any one.

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值