POJ 1722 DP
题意:
定义一种操作,操作i就是将a[i]-a[i+1]取出进行合并,再加入到a[i]的位置(我自己臆测的题意),进行n-1次操作后,会剩下一个数字。
给定a[1]~a[n]及目标t(最后剩下的数字),求操作顺序。
思路:
相当经典!
此题相当于在序列之间添加+-两种符号使得答案是t
最后按照+-号输出就是了
PS:第一个符号必定是减号!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
没有人能阻止我前进的步伐,除了我自己!