poj1722 SUBTRACT【線性DP】
阿新 • • 發佈:2018-10-12
hat ... least bit transform 如何選擇 sample 表示 script SUBTRACT
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.
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.
You can assume that at least one such sequence of contractions will exist for a given input.
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
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.
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.
Sample Input
5 4 12 10 4 3 5
Sample Output
2 3 2 1
Source
CEOI 1998
題意:
給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\n", i - cnt - 1); 53 cnt++; 54 } 55 } 56 for(int i = 2; i <= n; i++){ 57 if(ans[i] == -1){ 58 printf("1\n"); 59 } 60 } 61 } 62 return 0; 63 }
poj1722 SUBTRACT【線性DP】