POJ-1179 Polygon

链接http://poj.org/problem?id=1179

题意:开始时有一个由n个顶点构成的多边形。每个顶点被赋予一个整数值,每条边被赋予一个运算符“+”或“*”。所有边依次用整数从1到n编号。游戏第1步,将一条边删除。随后n-1步按以下方式操作:

1.选择一条边E以及由E连接着的2个顶点V1和V2;
2.用一个新的顶点取代边E以及由E连接着的2个顶点V1和V2。将由顶点V1和V2的整数值通过边E上的运算得到的结果赋予新顶点。
最后,所有边都被删除,游戏结束。游戏的得分就是所剩顶点上的整数值。要求求出游戏得分的最大值以及获得该最大值时第一步删除的边的编号。
思路:区间dp裸题,枚举要删除的第一条边,在这种情况下用区间dp求出能获得的最大值,与经典题石子合并不同,这道题的区间操作不止是相加,还有相乘,最大值有可能是通过两个负数相乘得来的,所以要记录最大值最小值,共有七种情况,写在代码里了(评论区哀嚎一片

代码:请忽略最上面的大佛(因为毫无用处

  1 //
  2 //                       _oo0oo_
  3 //                      o8888888o
  4 //                      88" . "88
  5 //                      (| -_- |)
  6 //                      0  =  /0
  7 //                    ___/`---'\___
  8 //                  .' \|     |// '.
  9 //                 / \|||  :  |||// 
 10 //                / _||||| -:- |||||- 
 11 //               |   | \  -  /// |   |
 12 //               | \_|  ''---/''  |_/ |
 13 //                 .-\__  '-'  ___/-. /
 14 //             ___'. .'  /--.--  `. .'___
 15 //          ."" '<  `.___\_<|>_/___.' >' "".
 16 //         | | :  `- \`.;` _ /`;.`/ - ` : | |
 17 //            `_.   \_ __ /__ _/   .-` /  /
 18 //     =====`-.____`.___ \_____/___.-`___.-'=====
 19 //                       `=---='
 20 //
 21 //
 22 //     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 23 //
 24 //               佛祖保佑         永无BUG
 25 //
 26 //
 27 //
 28  
 29 // #include<bits/stdc++.h>
 30 #include<iostream>
 31 #include<cstdio>
 32 #include<cmath>
 33 #include<string>
 34 #include<vector>
 35 #include<algorithm>
 36 #include<queue>
 37 #include<deque>
 38 #include<stack>
 39 #include<map>
 40 #include<cstring>
 41 
 42 #define inf 0x3f3f3f3f
 43 using namespace std;
 44  
 45 typedef long long ll;
 46 typedef long double ld;
 47  
 48 const int M = int(1e5)*3 + 5;
 49 const int mod = 10056;
 50  
 51 inline int lowbit(int x) {
 52     return x & (-x);
 53 }
 54 
 55 //op==1
 56 //++ ->+
 57 //maxn[l][r]=max(maxn[l][r],maxn[l][k-1]*maxn[k][r])
 58 //-- ->+
 59 //maxn[l][r]=max(maxn[l][r],minn[l][k-1]*minn[k][r])
 60 //++ ->+
 61 //minn[l][r]=min(minn[l][r],minn[l][k-1]*minn[k][r])
 62 //+- ->-
 63 //minn[l][r]=min(minn[l][r],minn[l][k-1]*minn[k][r])
 64 //+- ->-
 65 //minn[l][r]=min(minn[l][r],maxn[l][k-1]*minn[k][r])
 66 
 67 //op==0
 68 //++ ->+
 69 //maxn[l][r]=max(maxn[l][r],maxn[l][k-1]*maxn[k][r])
 70 //-- ->+
 71 //minn[l][r]=min(minn[l][r],minn[l][k-1]*minn[k][r])
 72 
 73 int maxn[105][105];
 74 int minn[105][105];
 75 int a[M];
 76 int op[M];
 77 int ans,cnt;
 78 int pos[M];
 79 int n;
 80 
 81 int dp(int x){
 82     memset(maxn,-inf,sizeof(maxn));
 83     memset(minn,inf,sizeof(minn));
 84     for(int i=x;i<=x+n-1;i++) minn[i][i]=maxn[i][i]=a[i];
 85 
 86     for(int len=1;len<=n;len++){
 87         for(int l=x;l<=x+n-len;l++){
 88             int r=l+len-1;
 89             for(int k=l+1;k<=r;k++){
 90                 if(op[k]==1){
 91                     maxn[l][r]=max(maxn[l][r],maxn[l][k-1]*maxn[k][r]);
 92                     maxn[l][r]=max(maxn[l][r],minn[l][k-1]*minn[k][r]);
 93                     minn[l][r]=min(minn[l][r],minn[l][k-1]*maxn[k][r]);
 94                     minn[l][r]=min(minn[l][r],minn[l][k-1]*minn[k][r]);
 95                     minn[l][r]=min(minn[l][r],maxn[l][k-1]*minn[k][r]);
 96                 }
 97                 else{
 98                     maxn[l][r]=max(maxn[l][r],maxn[l][k-1]+maxn[k][r]);
 99                     minn[l][r]=min(minn[l][r],minn[l][k-1]+minn[k][r]);
100                 }
101             }
102         }
103     }
104 
105     return maxn[x][x+n-1];
106 }
107 
108 int main()
109 {
110     cnt=0;
111     cin>>n;
112     for(int i=1;i<=n;i++){
113         char c;
114         cin>>c>>a[i];
115         a[i+n]=a[i];
116         if(c=='x') op[i]=op[i+n]=1;
117         else op[i]=op[i+n]=0;
118     }
119 
120     for(int i=1;i<=n;i++){          //枚举删哪条边
121         int tem=dp(i);
122         if(tem==ans){
123             pos[++cnt]=i;//这里不太明白为什么从0开始计数就WA了,可能是大佛不喜欢0
124         }
125         else if(tem>ans){
126             ans=tem;
127             pos[1]=i;
128             cnt=1;
129         }
130     }
131 
132     cout<<ans<<endl;
133     for(int i=1;i<=cnt;i++){
134         if(i==cnt) cout<<pos[i]<<endl;
135         else cout<<pos[i]<<" ";
136     }
137 
138     return 0;
139 }

备注:想了好长时间,最后才悟出来是个裸题

原文地址:https://www.cnblogs.com/harutomimori/p/11287322.html