代码改变世界

1176. Two Ends

2011-05-11 21:15  Min·zc  阅读(125)  评论(0编辑  收藏  举报
 1 /*采用倒推的dp,假设我们已经知道知道了从i到j段的最大差,然后去推导包含此段的最大差,如i-1到j+1段
 2  *因为是偶数个数字,所以最后一定会剩下两个,且刚好是A来选择,所以此时A一定是选择两个中最大的那个。
 3  *首先将长度为2的段全部初始化,注:34行
 4  *然后将长度从2开始逐渐增大到n-2,对于给定的一个子段,可以产生四种父段,如下
 5  *AB--,A--B,B--A,--BA    注:--代表子段
 6  *但是因为B是贪心的方式,所以就需要对以上的情况做一些限制条件,如第一种情况就要求B大于子段的最后一个,
 7  *这样才能保证B同学选择的是B号元素,否则B同学就会选择子段的最后一个元素
 8  *最后记得当两个数相同是需要选择左边的那一个
 9  *
10  *
11  *
12  */
13 
14 #include <iostream>
15 #include <memory.h>
16 #include <stdio.h>
17 #include <cmath>
18 using namespace std;
19 double num[1001];
20 double dp[1001][1001];
21 int main()
22 {
23         int n;
24         cin>>n;
25         int t=0;
26         while(n!=0)
27         {
28                 t++;
29                 memset(num,0,sizeof(num));
30                 memset(dp,0,sizeof(dp));
31 
32                 for(int i=0;i<n;i++)
33                         cin>>num[i];
34                 for(int i=0;i<n;i++)
35                         dp[i][i+1]=abs(num[i]-num[i+1]);
36                 for(int i=2;i<=n-2;i+=2)
37                         for(int j=0;j+i<=n;j++)
38                         {
39                                 int k=j+i-1;
40                         //   cout<<"j: "<<j<<"k: "<<k<<endl;
41                                 if(j-2>=0&&num[j-1]>=num[k])
42                                 {
43                                         dp[j-2][k]=max(dp[j-2][k],dp[j][k]+num[j-2]-num[j-1]);
44                                 //  cout<<j-2<<" "<<k<<dp[j-2][k]<<endl;
45                                 }
46                                 if(j-1>=0&&k+1<n&&num[k+1]>num[j])
47                                 {
48                                         dp[j-1][k+1]=max(dp[j-1][k+1],dp[j][k]+num[j-1]-num[k+1]);
49                                 }
50                                 if(j-1>=0&&k+1<n&&num[j-1]>=num[k])
51                                 {
52                                         dp[j-1][k+1]=max(dp[j-1][k+1],dp[j][k]+num[k+1]-num[j-1]);
53                                 //  cout<<j-1<<" "<<k+1<<dp[j-1][k+1]<<endl;
54                                 }
55                                 if(k+2<n&&num[j]<num[k+1])
56                                 {
57                                         dp[j][k+2]=max(dp[j][k+2],dp[j][k]+num[k+2]-num[k+1]);
58                                 //  cout<<j<<" "<<k+2<<dp[j][k+2]<<endl;
59                                 }
60                         }
61 
62                 cout<<"In game "<<t<<", the greedy strategy might lose by as many as "<<dp[0][n-1]<<" points.\n";
63         
64                 cin>>n;
65         }
66 }
67