新年趣事之打牌----VIJOS_1071----01背包加强版

目地址http://www.vijos.org/Problem_show.asp?id=1071


From xiaomengxian
新年趣事之打牌 新年趣事 系列 
描述 Description
过年的时候,大人们最喜欢的活动,就是打牌了。xiaomengxian不会打牌,只好坐在一边看着。
  这天,正当一群人打牌打得起劲的时候,突然有人喊道:“这副牌少了几张!”众人一数,果然是少了。于是这副牌的主人得意地说:“这是一幅特制的牌,我知道整副牌每一张的重量。只要我们称一下剩下的牌的总重量,就能知道少了哪些牌了。”大家都觉得这个办法不错,于是称出剩下的牌的总重量,开始计算少了哪些牌。由于数据量比较大,过了不久,大家都算得头晕了。
  这时,xiaomengxian大声说:“你们看我的吧!”于是他拿出笔记本电脑,编出了一个程序,很快就把缺少的牌找了出来。
  如果是你遇到了这样的情况呢?你能办到同样的事情吗?
输入格式 Input Format
第一行一个整数TotalW,表示剩下的牌的总重量。
  第二行一个整数N(1<N<=100),表示这副牌有多少张。
  接下来N行,每行一个整数Wi(1<=Wi<=1000),表示每一张牌的重量。
输出格式 Output Format
如果无解,则输出“0”;如果有多解,则输出“-1”;否则,按照升序输出丢失的牌的编号,相邻两个数之间用一个空格隔开。
样例输入 Sample Input
270
4
100
110
170
200

样例输出 Sample Output

2 4

首先要理解题目的意思。这个题目的意思是说,现在有一堆丢失了的牌,知道他们的总重量,然后知道每一种牌的重量,要你求到底是丢失了哪几张牌。如果无法确定则输出0,如果有很多种情况,则输出-1,否则按牌号的大小一次输出缺的牌。

由于本题目引入了重量的概念,所以既然剩下的牌的总重量知道,那我只需要用01背包方法求出怎样才能用给出的牌种组成剩下的牌,没拿进来的牌就是缺的牌。只不过我们要对这个做一个记录。记录哪些牌拿进来了,哪些没有。用一个数组judge[i]来记录是否加进来了。用数组num[v]来记录当把容量为V的正好装满的时候所用的牌的牌号i,用dp[v]来表示装满容量为v的所有方案数。初值dp[0]=1,其余为0.下面上代码更容易懂。

 

代码:

#include<iostream>
using namespace std;
int w[110];
bool ans[110];
int path[100010];
int dp[100010];
int main()
{
    int total,n,i,j;
    while(scanf("%d",&total)!=EOF)
    {
       scanf("%d",&n);
       for(i=1;i<=n;i++)
       {
          scanf("%d",&w[i]);
       }
       memset(dp,0,sizeof(dp));
       memset(ans,true,sizeof(ans));
       dp[0]=1;
       for(i=1;i<=n;i++)
        for(j=total;j>=w[i];j--)
           if(dp[j-w[i]]>0)
           {
             if(dp[j]==0) path[j]=i;
             dp[j]+=dp[j-w[i]];
           }
        if(dp[total]==0)
         { printf("0\n");break;}
        if(dp[total]>1)
        { printf("-1\n");break;}
        i=total;
        while(i>0)
        {
          ans[path[i]]=false;
          i=i-w[path[i]];
        }
        for(i=1;i<=n;i++)
          if(ans[i]) printf("%d ",i);
        printf("\n");
        
  }
  return 0;
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值