• hdu 6092


    http://acm.hdu.edu.cn/showproblem.php?pid=6092

    题意:有两个数组,分别为A数组和B数组,其中B数组是由A数组的子集的和构成的,B[i]代表A在子集的和为i的有多少个,且A,B都是个多重集,也就是说集合里面一个元素可能有多个

    思路:因为B数组里面是A的子集的和,那么B数组第一个存在的元素的位置,这个一定代表A里面i元素有B[i]个,因为没有比i要小的元素了。

    然后最开始想的是分解,把所有的元素分解成可以由哪些前面的数字的组合构成,然后觉得这样复杂度太高了,你每一个都要递归去找他的和因子,很明显这样不行

    然后看了一下官方题解,是用DP,反向的DP,这个思路确实是没有想到过的(其实还是太菜),感觉很巧妙

    就是一个B[i] -= B[i-j],j代表当前的A的和,为什么会这样呢

    因为B[I-J]代表什么,说明你用B[i-j]+B[j]可以构成一个B[I],减去B[i-j]就是代表减去了用这个i-j这个数构成的情况。

    那么最后剩下来的就是代表着B[I]这个数的个数,代表这个数不是由其他因子合成的个数。

    最后,我用java写,发现超时,然后用c++的cin输入还是超时,改scanf就可以了

    对这些东西还是不熟啊,java好的输入模板也没有

     1 #include <iostream>
     2 #include <stdio.h>
     3 using namespace std;
     4 
     5 int main()
     6 {
     7 
     8         int t, m, n;
     9         int locy;
    10         long long num[10005];
    11         scanf("%d", &t);
    12         while ((t--) > 0)
    13         {
    14             scanf("%d%d", &n, &m);
    15             for (int i = 0; i <= m; i++)
    16                 scanf("%lld",&num[i]);
    17             for (int i = 1; i <= n; i++)
    18             {
    19                 locy = 0;
    20                 for (int j = 1; j <= m; j++)
    21                     if (num[j] != 0)
    22                     {
    23                         locy = j;
    24                         break;
    25                     }
    26                 for (int j = locy; j <= m; j++)
    27                     num[j] -= num[j - locy];
    28                 if (i != n)
    29                     printf("%d ", locy);
    30                 else
    31                     printf("%d
    ", locy);
    32             }
    33     }
    34     return 0;
    35 }
  • 相关阅读:
    洛谷单元最短路标准版——spfa优化
    airline
    有依赖的背包
    挖地雷
    带分数问题
    子集和问题
    循环比赛日程表
    传纸条
    机器分配
    分组背包
  • 原文地址:https://www.cnblogs.com/Tree-dream/p/7323918.html
Copyright © 2020-2023  润新知