HDU 6092 Rikka with Subset 思维 递推

  题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6092

  题目描述: 给你一个集合的所有子集各个和, 让你找到这个集合, 输出字典序最小

  解题思路: 下标0上的数字肯定是1, 所以从下标为1的开始向后, 第一个不为零的数的下标肯定是集合中的一个数而且是最小的数......同时将这个数减减, 记住这个下标为cur(所以这个集合应该是唯一的?我没严格证明, 但是每一步取得值肯定都是唯一的啊, 而且从小到大)这样我们向后面偏移cur个单位, 如果两个数都不为0, 就说明cur这个数肯定做出了贡献(cur此时就最小的数, 所以不可能会有数儿组合取来等于cur), 这样筛了N遍就可以筛出来了

  代码: 

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxm = 1100002;
int a[maxm];
int m;
int ans[maxm];

int main(){
    int t;
    scanf( "%d", &t );
    while( t-- ) {
        int n;
        scanf( "%d%d", &n, &m );
        for( int i = 0; i <= m; i++ ) {
            scanf( "%d", a+i );
        }
        a[0] = 0;
        for( int i = 0; i < n; i++ ) {
            int j;
            for( j = 0; j <= m; j++ ) {
                if( a[j] ) break;
            }
            a[j]--;
            ans[i] = j;
            for( int k = j; k <= m; k++ ) {
                if( k+j <= m && a[k] && a[k+j] ) {
                    a[k+j] -= a[k];
                }
            }
        }
        for( int i = 0; i < n; i++ ) {
            i == 0 ? printf( "%d", ans[i] ) : printf( " %d", ans[i] );
        }
        printf( "\n" );
    }
    return 0;
}
View Code

  思考: 这道题一开始我就没敢向递推那里想.....因为我觉得判定哪个元素对哪个自己做出贡献是不能够的....但是题给出了这个和的已知条件.....哎, 自己太狭隘了.,.,....昨天那道DP还是没有A, 现在A掉

posted on 2017-08-08 20:42  FriskyPuppy  阅读(261)  评论(0编辑  收藏  举报

导航