【洛谷P4342】[IOI1998]Polygon
Polygon
比较裸的环形DP(也可以说是区间DP)
将环拆成链,复制到后面,做区间DP即可
#include<iostream> #include<cstdio> using namespace std; #define MAXN 110 #define INF 0x3f3f3f3f int n,f[MAXN][MAXN][2],ans=-INF; //f[l][r][0]表示最小值 f[l][r][1]表示最大值 char b[MAXN]; inline int read_num(){ int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); } while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } return x*f; } inline char read_char(){ char c=getchar(); while(c!='t'&&c!='x') c=getchar(); return c; } inline int Min(int d,int e,int f){ if(d<e) e=d; if(e<f) f=e; return f; } inline int Max(int d,int e,int f){ if(d>e) e=d; if(e>f) f=e; return f; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ b[i-1]=read_char(); b[i+n-1]=b[i-1]; f[i][i][1]=read_num(); f[i+n][i+n][1]=f[i+n][i+n][0]=f[i][i][0]=f[i][i][1]; } b[0]=0; for(int len=2;len<=n;len++) for(int l=1;l+len-1<=2*n;l++){ int r=l+len-1; f[l][r][1]=-INF; f[l][r][0]=INF; for(int k=l;k<r;k++) if(b[k]=='t'){ f[l][r][0]=min(f[l][r][0],f[l][k][0]+f[k+1][r][0]); f[l][r][1]=max(f[l][r][1],f[l][k][1]+f[k+1][r][1]); } else{ f[l][r][0]=Min(f[l][r][0],f[l][k][0]*f[k+1][r][1],f[l][k][1]*f[k+1][r][0]); f[l][r][1]=Max(f[l][r][1],f[l][k][0]*f[k+1][r][0],f[l][k][1]*f[k+1][r][1]); } } for(int i=1;i<=n;i++) ans=max(ans,f[i][i+n-1][1]); printf("%d\n",ans); for(int i=1;i<=n;i++) if(f[i][i+n-1][1]==ans) printf("%d ",i); puts(""); return 0; }