dp[i][j]表示前i个元素,子集和为j的个数。d[i][j] = d[i][j] + d[i-1][j-k] (第i个元素的值为k)。这里可以优化成一维数组
比如序列为 1 2 3,每一步的dp值为
1 0 0 0 0 0 0 (d[0][0]=1)
1 1 0 0 0 0 0
1 1 1 1 0 0 0
1 1 1 2 1 1 1
最终的序列就是题目给出的B序列,把B序列减去每一次dp得到的序列,第一个非0值就是a序列中的值
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define max_n 10010 using namespace std; int a[max_n], b[max_n], dp[max_n]; //dp[i]表示:和为i的子集个数 int main() { // freopen("in.txt","r",stdin); int t, n, m; scanf("%d", &t); while(t--) { memset(dp, 0, sizeof(dp)); scanf("%d %d", &n, &m); for(int i = 0; i <= m; i++) scanf("%d", &b[i]); dp[0] = 1; //初始化值 int num = 0; for(int i = 1; i <= m; i++) { int t = b[i] - dp[i];//A序列中值为i的个数 for(int j = 0; j < t; j++) { a[num++] = i; //对A序列赋值 for(int k = m; k>= i; k--) //处理成01背包 { dp[k] += dp[k - i]; //计算和为k的A子集个数 } } } for(int i = 0; i < num; i++) { if(i > 0) printf(" "); printf("%d", a[i]);//输出A序列 } printf(" "); } return 0; }