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; }
思考: 这道题一开始我就没敢向递推那里想.....因为我觉得判定哪个元素对哪个自己做出贡献是不能够的....但是题给出了这个和的已知条件.....哎, 自己太狭隘了.,.,....昨天那道DP还是没有A, 现在A掉
posted on 2017-08-08 20:42 FriskyPuppy 阅读(261) 评论(0) 编辑 收藏 举报