Skip to content

13031: 【原3031】露子的野餐

题目

题目描述

author: sonicmisora 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/3031

【题目描述】

今天是个难得的风和日丽的星期天,你现在要去和露子吃野餐。你们一共带了n袋食物准备享用。但是不幸的事情发生了,你们到达草地时发现有的食物不见了。为了找出是哪些东西不见了,你们决定通过计算来解决。露子告诉你n袋食物每袋的重量,以及现在所有食物的总重量。为了能更开心地享受野餐,你掏出了电脑

【输入格式】

第一行有一个数m,表示当前有的食物的总重量。 第二行有一个数n,表示出门时一共带了n袋食物。 接下来一共有n行,每行表示第i号食物的重量Mi。

【输出格式】

输出仅包含一行: 如果无解,请输出0; 如果有多组解,请输出-1; 否则,请按从小到大的顺序依次输出丢失的食物的编号,它们之间用空格隔开。

【样例输入】

500
4
200
400
150
300

【样例输出】

2 3

【数据规模】

1<=n<=100, 1<=Mi<=1000. 即总袋数小于等于100,每袋食物重量小于等于1000。 每个测试点2s时限。

【提示】

使用动态规划解决。

WashSwang's solution

#include <iostream>
using namespace std;
int m,n,w[101],dp[101][100001],ans[101],ansn;
int main() {
    cin>>m>>n;
    for (int i=1;i<=n;++i) {
        cin>>w[i];
        m-=w[i];
    }
    m=-m;
    dp[0][0]=1;
    for (int i=1;i<=n;++i)
        for (int j = m; j >= 0; --j) {
            dp[i][j] = dp[i - 1][j];
            if (j>=w[i]) dp[i][j]+=dp[i - 1][j - w[i]];
        }
    if (dp[n][m]==0) cout<<0<<endl;
    else if (dp[n][m]>1) cout<<-1<<endl;
    else{
        ansn=0;
        for (int i=n;i>=1;--i)
            if (m>=w[i]&&dp[i - 1][m - w[i]]) {
                ans[ansn++] = i;
                m-=w[i];
            }
        for (int i=ansn-1;i>=0;--i)
            cout<<ans[i]<<' ';
    }
    return 0;
}