POJ 1722 DP

题意:

定义一种操作,操作i就是将a[i]-a[i+1]取出进行合并,再加入到a[i]的位置(我自己臆测的题意),进行n-1次操作后,会剩下一个数字。

给定a[1]~a[n]及目标t(最后剩下的数字),求操作顺序。

 

思路:

相当经典!

此题相当于在序列之间添加+-两种符号使得答案是t

最后按照+-号输出就是了

PS:第一个符号必定是减号!

 

View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 
 5 #define N 120
 6 #define WC 10000
 7 
 8 using namespace std;
 9 
10 int n,t,a[N],pre[N],dp[N][20001];
11 
12 void read()
13 {
14     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
15 }
16 
17 void go()
18 {
19     memset(dp,0,sizeof dp);
20     memset(pre,0,sizeof pre);
21     dp[1][a[1]+WC]=2;
22     dp[2][a[1]-a[2]+WC]=1;
23     for(int i=3;i<=n;i++)
24         for(int j=0;j<=20000;j++)
25             if(dp[i-1][j]>0)
26             {
27                 if(j+a[i]<=20000) dp[i][j+a[i]]=2;
28                 if(j-a[i]>=0) dp[i][j-a[i]]=1;
29             }
30     for(int i=n,j=t+WC;i>=1;i--)
31     {
32         if(dp[i][j]==2)
33         {
34             pre[i]=2;
35             j-=a[i];
36         }
37         else if(dp[i][j]==1)
38         {
39             pre[i]=1;
40             j+=a[i];
41         }
42     }
43     int cnt=0;
44     for(int i=2;i<=n;i++)
45         if(pre[i]==2) printf("%d\n",i-1-cnt),cnt++;
46     for(int i=2;i<=n;i++)
47         if(pre[i]==1) puts("1");
48 }
49 
50 int main()
51 {
52     while(scanf("%d%d",&n,&t)!=EOF)
53     {
54         read();
55         go();
56     }
57     return 0;
58 }
posted @ 2012-10-04 14:45  proverbs  阅读(354)  评论(0编辑  收藏  举报