poj1722 SUBTRACT线性DP
Posted wyboooo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj1722 SUBTRACT线性DP相关的知识,希望对你有一定的参考价值。
SUBTRACT
Time Limit: 1000MS | Memory Limit: 10000K | |||
Total Submissions: 2037 | Accepted: 901 | Special Judge |
Description
We are given a sequence of N positive integers a = [a1, a2, ..., aN] on which we can perform contraction operations.
One contraction operation consists of replacing adjacent elements ai and ai+1 by their difference ai-ai+1. For a sequence of N integers, we can perform exactly N-1 different contraction operations, each of which results in a new (N-1) element sequence.
Precisely, let con(a,i) denote the (N-1) element sequence obtained from [a1, a2, ..., aN] by replacing the elements ai and ai+1 by a single integer ai-ai+1 :
con(a,i) = [a1, ..., ai-1, ai-ai+1, ai+2, ..., aN]
Applying N-1 contractions to any given sequence of N integers obviously yields a single integer.
For example, applying contractions 2, 3, 2 and 1 in that order to the sequence [12,10,4,3,5] yields 4, since :
Given a sequence a1, a2, ..., aN and a target number T, the problem is to find a sequence of N-1 contractions that applied to the original sequence yields T.
One contraction operation consists of replacing adjacent elements ai and ai+1 by their difference ai-ai+1. For a sequence of N integers, we can perform exactly N-1 different contraction operations, each of which results in a new (N-1) element sequence.
Precisely, let con(a,i) denote the (N-1) element sequence obtained from [a1, a2, ..., aN] by replacing the elements ai and ai+1 by a single integer ai-ai+1 :
con(a,i) = [a1, ..., ai-1, ai-ai+1, ai+2, ..., aN]
Applying N-1 contractions to any given sequence of N integers obviously yields a single integer.
For example, applying contractions 2, 3, 2 and 1 in that order to the sequence [12,10,4,3,5] yields 4, since :
con([12,10,4,3,5],2) = [12,6,3,5]
con([12,6,3,5] ,3) = [12,6,-2]
con([12,6,-2] ,2) = [12,8]
con([12,8] ,1) = [4]
Given a sequence a1, a2, ..., aN and a target number T, the problem is to find a sequence of N-1 contractions that applied to the original sequence yields T.
Input
The first line of the input contains two integers separated by blank character : the integer N, 1 <= N <= 100, the number of integers in the original sequence, and the target integer T, -10000 <= T <= 10000.
The following N lines contain the starting sequence : for each i, 1 <= i <= N, the (i+1)st line of the input file contains integer ai, 1 <= ai <= 100.
The following N lines contain the starting sequence : for each i, 1 <= i <= N, the (i+1)st line of the input file contains integer ai, 1 <= ai <= 100.
Output
Output should contain N-1 lines, describing a sequence of contractions that transforms the original sequence into a single element sequence containing only number T. The ith line of the output file should contain a single integer denoting the ithcontraction to be applied.
You can assume that at least one such sequence of contractions will exist for a given input.
You can assume that at least one such sequence of contractions will exist for a given input.
Sample Input
5 4 12 10 4 3 5
Sample Output
2 3 2 1
Source
题意:
给N个数,每次选定一个i,用a[i] - a[i+1]的结果取代a[i]和a[i+1]。操作N-1次之后,就只剩下1个数。问如何选择,可以使这个数恰好是T
思路:
我们可以发现,这个序列每次用减来取代的话,其实就是在n个数之前加上正负,然后让他们都加起来的和结果是T。
而且a[1]一定是正,a[2]一定是负。
于是我们用dp[i][j]来表示第i个数得到分数j时的符号,1表示是加,-1表示是减,0表示没有扩展到。【我怎样才能聪明地想到要这样来表示呢】
我们枚举i,j,判断上一个状态i-1有没有扩展到当前分数j。如果有,那么dp[i][j + a[i]] = 1, dp[i][j - a[i]] = -1
然后我们从dp[n][t]开始倒推出每一个元素之前的符号。ans[i]表示的就是a[i]前的符号。
那么方案该怎么输出?
先去处理所有的加号,相当于把所有的加号都挪去了原来a3的位置,这样最后处理减号的时候,减a2就可以负负得正了。
然后处理减号,把所有的减号都挪到了原来a2的位置,给a1来减。
1 //#include <bits/stdc++.h> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<stdio.h> 6 #include<cstring> 7 #include<vector> 8 #include<map> 9 #include<set> 10 11 #define inf 0x3f3f3f3f 12 using namespace std; 13 typedef long long LL; 14 15 int n, t; 16 int a[105]; 17 int dp[105][20010], ans[105]; 18 const int base = 10005; 19 20 int main() 21 { 22 while(scanf("%d%d", &n, &t) != EOF){ 23 for(int i = 1; i <= n; i++){ 24 scanf("%d", &a[i]); 25 } 26 memset(dp, 0, sizeof(dp)); 27 dp[1][a[1] + base] = 1; 28 dp[2][a[1] - a[2] + base] = -1; 29 for(int i = 3; i <= n; i++){ 30 for(int j = -10000 + base; j <= 10000 + base; j++){ 31 if(dp[i - 1][j] != 0){ 32 dp[i][j + a[i]] = 1; 33 dp[i][j - a[i]] = -1; 34 } 35 } 36 } 37 38 int want = t + base; 39 for(int i = n; i >= 2; i--){ 40 ans[i] = dp[i][want]; 41 if(ans[i] == 1){ 42 want -= a[i]; 43 } 44 else if(ans[i] == -1){ 45 want += a[i]; 46 } 47 } 48 49 int cnt = 0; 50 for(int i = 2; i <= n; i++){ 51 if(ans[i] == 1){ 52 printf("%d ", i - cnt - 1); 53 cnt++; 54 } 55 } 56 for(int i = 2; i <= n; i++){ 57 if(ans[i] == -1){ 58 printf("1 "); 59 } 60 } 61 } 62 return 0; 63 }
以上是关于poj1722 SUBTRACT线性DP的主要内容,如果未能解决你的问题,请参考以下文章