1. 程式人生 > >poj1722 SUBTRACT【線性DP】

poj1722 SUBTRACT【線性DP】

hat ... least bit transform 如何選擇 sample 表示 script

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 :
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】