URAL 1244 Gentlemen

1244. Gentlemen

Time limit: 0.5 second
Memory limit: 64 MB
Let's remember one old joke:
Once a gentleman said to another gentleman:
— What if we play cards?
— You know, I haven't played cards for ten years…
— And I haven't played for fifteen years…
So, little by little, they decided to resurrect their youth. The first gentleman asked a servant to bring a pack of cards, and before starting playing out weighed in his hand the pack.
— It seems to me, one card is missing from the pack… — he said and gave the pack to the other gentleman.
— Yes, the nine of spades, — the man agreed.
An incomplete pack of cards is given. The program should determine which cards are missing.

Input

The first line contains a positive integer, which is the weight in milligrams of the given incomplete pack. The second line contains an integer N, 2 ≤ N ≤ 100 — the number of cards in the complete pack. In the next N lines there are integers from 1 to 1000, which are the weights of the cards in milligrams. It's guaranteed that the total weight of all cards in the complete pack is strictly greater than the weight of the incomplete pack.

Output

If there is no solution, then output the single number 0. If there are more than one solutions, then you should write −1. Finally, if it is possible to determine unambiguously which cards are missing in the incomplete pack as compared to the complete one, then output the numbers of the missing cards separated with a space in ascending order.

Samples

inputoutput
270
4
100
110
170
200
2 4
270
4
100
110
160
170
-1
270
4
100
120
160
180
0
题目翻译:
给出一幅不完全的纸牌.程序应该算出哪些牌丢失了.

第一行包含一个整数,表示给出的一副(不完全的)纸牌的总重量,单位毫克.第2行包含一个正整数N,1<N≤100--这幅不完全的纸牌中的纸牌数.接下来的N行是N个数,分别表示N张纸牌的重量,单位毫克.  

如果无解,输出一个数0.如果不止一个解,则你应输出-1.最后,如果能够明确的确定与完整的一幅纸牌相比在这个不完整的纸牌中缺少哪些纸牌,按递增顺序输出缺失纸牌的序号,以空格分开.  

题解:
一道比较简单的背包
状态转移: if ( dp [ j ]) dp [ j + a [ i ]]+= dp [ j ]
还需要一个数组记录路径,最后回溯输出即可
代码如下:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
int dp[100002];
int p[100002];
int a[102];
int ans[102];
int w,n;
void print()
{
	int i,j=0;
	for(i=n;i>=1;i--)
	{
		if(p[w]==i)
		{
			ans[++j]=i;
			w=w-a[i];
		}
	}
	for(i=j;i>1;i--)
		printf("%d ",ans[i]);
	printf("%d\n",ans[1]);
}
int main()
{
	int sum=0;
	scanf("%d%d",&w,&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		sum+=a[i];
	}
	w=sum-w;
	if(w<0)
	{
		printf("0\n");
		return 0;
	}
	dp[0]=1;
	for(int i=1;i<=n;i++)
	{
		for(int j=w-a[i];j>=0;j--)
		{
			if(dp[j])
			{
				if(!dp[j+a[i]])
					p[j+a[i]]=i;  //记录
				dp[j+a[i]]+=dp[j];
			}
		}
	}
	switch (dp[w])
	{
		case 0:
			printf("0");
			break;
		case 1:
			print();
			break;
		default :
			printf("-1");
			break;
	}
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值