zoukankan      html  css  js  c++  java
  • vijos 1071 01背包+输出路径

    描述

    过年的时候,大人们最喜欢的活动,就是打牌了。xiaomengxian不会打牌,只好坐在一边看着。

    这天,正当一群人打牌打得起劲的时候,突然有人喊道:“这副牌少了几张!”众人一数,果然是少了。于是这副牌的主人得意地说:“这是一幅特制的牌,我知道整副牌每一张的重量。只要我们称一下剩下的牌的总重量,就能知道少了哪些牌了。”大家都觉得这个办法不错,于是称出剩下的牌的总重量,开始计算少了哪些牌。由于数据量比较大,过了不久,大家都算得头晕了。

    这时,xiaomengxian大声说:“你们看我的吧!”于是他拿出笔记本电脑,编出了一个程序,很快就把缺少的牌找了出来。

    如果是你遇到了这样的情况呢?你能办到同样的事情吗?

    格式

    输入格式

    第一行一个整数TotalW,表示剩下的牌的总重量。

    第二行一个整数N(1<N<=100),表示这副牌有多少张。

    接下来N行,每行一个整数Wi(1<=Wi<=1000),表示每一张牌的重量。

    输出格式

    如果无解,则输出“0”;如果有多解,则输出“-1”;否则,按照升序输出丢失的牌的编号,相邻两个数之间用一个空格隔开。

    样例1

    样例输入1[复制]

    270
    4
    100
    110
    170
    200

    样例输出1[复制]

    2 4

    题意:就是个裸的01背包,加个路径输出。

    思路:记录下当前值下的前一个值,顺带记录序号,最后遍历一遍,筛出没出现过的数就好了。

    /** @Date    : 2016-11-29-08.14
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version :
      */
    
    #include<bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+2000;
    
    
    int w, n;
    int dp[100010];
    int re[100010];
    int mp[100010];
    int a[110];
    int main()
    {
        while(cin >> w >> n)
        {
            for(int i = 1; i <= n; i++)
            {
                scanf("%d", a + i);
            }
    
            MMF(dp);
            MMF(re);
            int flag = 0;
            dp[0] = 1;
            for(int i = 1; i <= n; i++)
            {
                for(int j = w; j >= 0; j--)
                {
                    if(j >= a[i] && dp[j-a[i]])
                    {
                        dp[j] += dp[j - a[i]];
                        if(dp[j] == 1)
                            re[j] = j - a[i], mp[j] = i;
                    }
                }
            }
            if(!dp[w])
                printf("0
    ");
            else if(dp[w] > 1)
                printf("-1
    ");
            else
            {
                int t = w;
                while(t != 0)
                {
                    a[mp[t]] = -1;
                    t = re[t];
                }
                for(int i = 1; i <= n; i++)
                {
                    if(a[i] != -1)
                    {
                        if(flag)
                            printf(" ");
                        printf("%d", i);
                        flag = 1;
                    }
                }
                printf("
    ");
            }
    
        }
        return 0;
    }
    
    
  • 相关阅读:
    HDFS的工作流程分析
    linux文本分析利器awk
    二叉树遍历
    tomcat 工作原理简析
    徐汉彬:Web系统大规模并发——电商秒杀与抢购
    牛人博客 列表
    消息队列 概念 配合SpringBoot使用Demo
    Redis 实例排除步骤
    Java分布式 一些概念理解
    消息成功失败回调demo
  • 原文地址:https://www.cnblogs.com/Yumesenya/p/6115332.html
Copyright © 2011-2022 走看看