Vijos 1565 多边形 【区间DP】
描述
zgx给了你一个n边的多边形,这个多边形每个顶点赋予一个值,每条边都被标上运算符号+或*,对于这个多边形有一个游戏,游戏的步骤如下:
(1)第一步,删掉一条边;
(2)接下来n-1步,每步对剩下的边中的一条进行操作,用一个新的顶点取代这条边。将这条被取代的边两端的顶点的整数值通过边上的运算得到的结果赋予新顶点。最后,所有的边被删除,只剩一个定点,这个定点的整数值就是游戏的最后得分。
你要做的就是算出给你的多边形能得到的最高分和最低分。
格式
输入格式
第一行,n;
第二行,n条边的运算符;
第三行,n个顶点的初始值;注:边和顶点都是按顺序输入,
第一个输入的边连接第一个输入的第二个输入的顶点。输出格式
最大值;
最小值。样例1
样例输入1
4 +++* 1 1 1 1
样例输出1
4 3
限制
各个测试点2s
提示
n<=50
解释样例:
1
+ +
1 1
* +
1
最大值:1+1+1+1=4或(1+1)*(1+1);
最小值:1*1+1+1=3;
题目链接:
题目大意:
N个数顺序排成一个圈,每两个数之间有一条边,+或*
题目要求删去一条边之后,任意顺序删掉一条边,并且把这条边两边的端点按照边上的符号运算,求最大最小值。
题目思路:
【区间DP】
可能是负数!!!
一开始居然傻逼的去做符号。。
首先破环,复制一遍数组到i+n。接着区间DP
max[i][j]和min[i][j]表示第i个数到第j个数所能获得的最大值和最小值。
然后枚举中间的断点。注意乘号的时候max=max*max,min*min。min=min*min,max*min。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // 2 //by coolxxx 3 /* 4 #include<iostream> 5 #include<algorithm> 6 #include<string> 7 #include<iomanip> 8 #include<map> 9 #include<stack> 10 #include<queue> 11 #include<set> 12 #include<bitset> 13 #include<memory.h> 14 #include<time.h> 15 #include<stdio.h> 16 #include<stdlib.h> 17 #include<string.h> 18 #include<math.h> 19 //#include<stdbool.h> 20 #define min(a,b) ((a)<(b)?(a):(b)) 21 #define max(a,b) ((a)>(b)?(a):(b)) 22 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b)) 23 */ 24 #include<bits/stdc++.h> 25 #pragma comment(linker,"/STACK:1024000000,1024000000") 26 #define abs(a) ((a)>0?(a):(-(a))) 27 #define lowbit(a) (a&(-a)) 28 #define sqr(a) ((a)*(a)) 29 #define mem(a,b) memset(a,b,sizeof(a)) 30 #define eps (1e-8) 31 #define J 10000 32 #define mod 1000000007 33 #define MAX 0x7f7f7f7f 34 #define PI 3.14159265358979323 35 #define N 104 36 using namespace std; 37 typedef long long LL; 38 double anss; 39 LL aans; 40 int cas,cass; 41 int n,m,lll,ans; 42 43 LL a[N]; 44 char ch[N]; 45 bool c[N]; 46 LL maxx[N][N],minn[N][N]; 47 int main() 48 { 49 #ifndef ONLINE_JUDGE 50 freopen("1.txt","r",stdin); 51 // freopen("2.txt","w",stdout); 52 #endif 53 int i,j,k,l; 54 int x,y,z; 55 // for(scanf("%d",&cass);cass;cass--) 56 // for(scanf("%d",&cas),cass=1;cass<=cas;cass++) 57 // while(~scanf("%s",s)) 58 while(~scanf("%d",&n)) 59 { 60 for(i=0;i<N;i++) 61 for(j=0;j<N;j++) 62 maxx[i][j]=-MAX,minn[i][j]=MAX; 63 64 scanf("%s",ch+1); 65 for(i=1;i<=n;i++) 66 { 67 if(ch[i]=='*')c[i+n]=c[i]=1; 68 else c[i+n]=c[i]=0; 69 } 70 for(i=1;i<=n;i++) 71 { 72 scanf("%lld",&a[i]); 73 a[n+i]=a[i]; 74 maxx[i][i]=maxx[i+n][i+n]=minn[i][i]=minn[i+n][i+n]=a[i]; 75 } 76 for(l=1;l<n;l++) 77 { 78 for(i=1;i+l<=n+n;i++) 79 { 80 j=i+l; 81 for(k=i;k<j;k++) 82 { 83 if(c[k]) 84 { 85 maxx[i][j]=max(maxx[i][j],maxx[i][k]*maxx[k+1][j]); 86 maxx[i][j]=max(maxx[i][j],minn[i][k]*minn[k+1][j]); 87 88 minn[i][j]=min(minn[i][j],minn[i][k]*minn[k+1][j]); 89 minn[i][j]=min(minn[i][j],maxx[i][k]*minn[k+1][j]); 90 minn[i][j]=min(minn[i][j],minn[i][k]*maxx[k+1][j]); 91 } 92 else 93 { 94 maxx[i][j]=max(maxx[i][j],maxx[i][k]+maxx[k+1][j]); 95 minn[i][j]=min(minn[i][j],minn[i][k]+minn[k+1][j]); 96 } 97 } 98 } 99 } 100 LL Min=MAX,Max=-MAX; 101 for(i=1;i<=n;i++) 102 { 103 Min=min(Min,minn[i][i+n-1]); 104 Max=max(Max,maxx[i][i+n-1]); 105 } 106 printf("%lld\n%lld\n",Max,Min); 107 puts(""); 108 } 109 return 0; 110 } 111 /* 112 // 113 114 // 115 */