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