poj 1179 polygon

题目大意:
有一个n个点的环,每条边上有加号或乘号,然后这条边所连的两个点的权值就依据这条边上的符号来进行运算,将运算的结果作为一个新的节点。

问先去掉一条边,最后将所有边都进行运算,最后得到的最终点的权值最大是多少(输入时t表示该边为加号,x表示该边为乘号


思路:
首先分析题目可以看出应为dp。题目要求删除一条边后的最大得分,那么我们只要求出来从第i个顶点到第i-1个顶点(走一大圈)的最大分数就好了

可以想到列dp[i][k]表示以第i个顶点为起点顺时针走k个顶点的最大得分。(k>=1)

可以枚举分割点求出dp[i][k],又因为是一个环,枚举分割点较为麻烦,因此枚举分割长度j:

得到dp方程 dp[i][j]与dp[i+j][k-j]之间运算(1<=j<k)

但是有一个问题 因为存在负数,所以可能有两个负数相乘得到最大值

因此我们还需要求出以第i个顶点为起点顺时针走k个顶点的最小得分

这样就用两个数组maxf,minf记录一下

其中minf中两个乘的情况有些麻烦:求五个情况的最小值(minf[i][len],minf[i][j]*minf[(i+j)%n][len-j],minf[i][j]*maxf[(i+j)%n][len-j],maxf[i][j]*maxf[(i+j)%n][len-j],maxf[i][j]*minf[(i+j)%n][len-j])

最后搞一下长度为n就好了

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<memory.h>
 7 #include<vector>
 8 #include<queue>
 9 #include<cstdlib>
10 #define MAXN 55
11 using namespace std;
12 bool edge[MAXN];
13 char ch;
14 int ans,maxf[55][55],minf[55][55],a,n;
15 int main()
16 {
17     scanf("%d",&n);
18     for(int i=0;i<MAXN;i++)
19         for(int j=0;j<MAXN;j++) {maxf[i][j]=-214748364;minf[i][j]=214748364;}
20     for(int i=0;i<n;i++) 
21     {
22         cin>>ch>>a;
23         if(ch=='t') edge[i]=true;
24         maxf[i][1]=minf[i][1]=a;
25     }
26     for(int len=2;len<=n;len++)
27     {
28         for(int i=0;i<n;i++)
29         {
30             for(int j=1;j<len;j++)
31             {
32                 if(edge[(i+j)%n]==true) 
33                 {
34                     maxf[i][len]=max(maxf[i][len],maxf[i][j]+maxf[(i+j)%n][len-j]);
35                     minf[i][len]=min(minf[i][len],minf[i][j]+minf[(i+j)%n][len-j]);
36                 }
37                 if(edge[(i+j)%n]==false) 
38                 {
39                     maxf[i][len]=max(maxf[i][len],max(maxf[i][j]*maxf[(i+j)%n][len-j],minf[i][j]*minf[(i+j)%n][len-j]));
40                     minf[i][len]=min(minf[i][len],min(min(minf[i][j]*minf[(i+j)%n][len-j],minf[i][j]*maxf[(i+j)%n][len-j]),min(maxf[i][j]*maxf[(i+j)%n][len-j],maxf[i][j]*minf[(i+j)%n][len-j])));
41                 }
42             }
43             if(len==n) ans=max(ans,maxf[i][len]);
44         }
45     }
46     printf("%d\n",ans);
47     bool flag=false;
48     for(int i=0;i<n;i++)
49     {
50         if(maxf[i][n]==ans&&flag==true) printf(" %d",i+1);
51         if(maxf[i][n]==ans&&flag==false) {printf("%d",i+1);flag=true;}
52     }
53 }
View Code

 

 

 

posted @ 2017-07-03 16:16  jack_yyc  阅读(139)  评论(0编辑  收藏  举报