多边形游戏——区间dp
此题类似石子合并,将环状多边形转换成链,由n转入2*n+1个字符。
总数量不能变,所以一点一点向后推移;
先进行一个循环,决定去掉那条边,再加n,向后推移;
f[i][j],表示从i到j的最优解;
每一个点必定是由两个点组成,so,在i,j区间枚举分割点,注意分割点不能等于j;
因为这题中,数字有正有负,必然要考虑负负得正的情况
例如,-1000*-1000=1000000 100*100=10000 而1000000>10000,但-1000却小于100;
所以每一次合并必然要考虑最小值和最大值;
如果下一次合并时,符号是‘+’,那就直接将最大值和最小值相加;
若是‘*’,那就将大*大,大*小,小*大,小*小四种比较一下,寻找最大值和最小值;
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int n,shu[150],f[150][150][3],sum[150][150],ff[150]={0},ma,mb,a,b,c,d; char fu[150]; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>fu[i]>>shu[i];//先输入符号,在输入数字 } for(int i=n+1;i<=2*n;i++) { shu[i]=shu[i-n]; fu[i]=fu[i-n]; } for(int i=1;i<=n;i++) { for(int o=1;o<=2*n;o++) { for(int p=1;p<=2*n;p++) { f[o][p][1]=-9999999;//求大值,初始化最小 f[o][p][2]=9999999;//求小值,初始化最大 } } for(int q=1;q<=2*n;q++)//初始化区间dp { f[q][q][1]=shu[q]; f[q][q][2]=shu[q]; if(fu[q+1]=='t') { f[q][q+1][1]=shu[q]+shu[q+1]; f[q][q+1][2]=shu[q]+shu[q+1]; } if(fu[q+1]=='x') { f[q][q+1][1]=shu[q]*shu[q+1]; f[q][q+1][2]=shu[q]*shu[q+1]; } } for(int l=2;l<=n;l++) { for(int j=i;j<=i+n-l;j++) { int k=j+l-1; for(int x=j;x<k;x++)//一定要小于k,因为后面有x+1; { if(fu[x+1]=='t'&&f[j][k][1]<f[j][x][1]+f[x+1][k][1])f[j][k][1]=f[j][x][1]+f[x+1][k][1]; if(fu[x+1]=='t'&&f[j][k][2]>f[j][x][2]+f[x+1][k][2])f[j][k][2]=f[j][x][2]+f[x+1][k][2]; if(fu[x+1]=='x') { a=f[j][x][1]*f[x+1][k][1]; b=f[j][x][2]*f[x+1][k][1]; c=f[j][x][1]*f[x+1][k][2]; d=f[j][x][2]*f[x+1][k][2]; f[j][k][1]=max(max(max(a,b),max(c,d)),f[j][k][1]); f[j][k][2]=min(min(min(a,b),min(c,d)),f[j][k][2]); } } } } ff[i]=f[i][i+n-1][1]; } ma=-1000000; for(int i=1;i<=n;i++)//寻找最大值 { if(ma<ff[i]) { ma=ff[i]; mb=i; } } cout<<ma<<endl; for(int i=1;i<=n;i++) { if(ff[i]==ma) { cout<<i<<" ";//输出可以断第几个 } } } /* 4 120 x 2 x 3 x 4 x 5 1 2 3 4 6 10000 x -10 x -10 x -10 t 10 t 10 t 10 6 7 300000 x -10 x -10 x -10 x -10 t 10 t 10 t 10 5 以上是三组测试数据*/
以上是个人见解,,如有不妥请评论区发表意见
以下是改进后的代码
#include<bits/stdc++.h> using namespace std; int n,num[105],dp1[105][105],dp2[105][105],maxn[55],maxx; char fu[105]; int main() { memset(dp1,0x8f,sizeof(dp1)); memset(dp2,0x3f,sizeof(dp2)); cin>>n; for(int i=1;i<=n;i++){ cin>>fu[i]>>num[i]; fu[n+i]=fu[i]; num[n+i]=dp1[i][i]=dp1[n+i][n+i]=dp2[i][i]=dp2[n+i][n+i]=num[i]; } for(int o=1;o<=n;o++){ for(int l=2;l<=n;l++){ for(int i=o;i<=o+n-l;i++){ int j=i+l-1; for(int k=i+1;k<=j;k++){ int a,b,c,d; if(fu[k]=='t'){ a=dp1[i][k-1]+dp1[k][j]; b=dp2[i][k-1]+dp2[k][j]; dp1[i][j]=max(dp1[i][j],a); dp2[i][j]=min(dp2[i][j],b); } if(fu[k]=='x'){ a=dp1[i][k-1]*dp1[k][j]; b=dp1[i][k-1]*dp2[k][j]; c=dp2[i][k-1]*dp2[k][j]; d=dp2[i][k-1]*dp1[k][j]; dp1[i][j]=max(dp1[i][j],max(a,max(b,max(c,d)))); dp2[i][j]=min(dp2[i][j],min(a,min(b,min(c,d)))); } } } } maxn[o]=dp1[o][o+n-1]; maxx=max(maxx,dp1[o][o+n-1]); } cout<<maxx<<endl; for(int i=1;i<=n;i++){ if(maxn[i]==maxx) cout<<i<<" "; } }
QQ:2953174821