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 }

你可能感兴趣的:(poj)