石子合併~區間dp基礎
阿新 • • 發佈:2019-02-14
出處:NOI1995普及組 RQNOJ490
一次AC,沒什麼好說的,注意細節就好,第一個下標從大到小迴圈,第二個下表從小到大迴圈且不超過n。
#include<stdio.h> #include<iostream> using namespace std; const int N=200; const int INF=0x3fffffff; int main() { int n,i,j,k,maxs,mins; int dp1[N][N],dp2[N][N],a[N],sum[N]; while (~scanf("%d",&n)) { sum[0]=0; for (i=1;i<=n;i++) { scanf("%d",a+i); a[i+n]=a[i]; sum[i]=sum[i-1]+a[i]; } for (i=n+1;i<n+n;i++) sum[i]=sum[i-1]+a[i]; for (i=0;i<n+n;i++) for (j=0;j<n+n;j++) dp1[i][j]=dp2[i][j]=0; for (i=n+n;i>0;i--) { for (j=i+1;j<i+n&&j<n+n;j++) { maxs=-1,mins=INF; for (k=i;k<j;k++) { maxs=(dp1[i][k]+dp1[k+1][j])>maxs?dp1[i][k]+dp1[k+1][j]:maxs; mins=(dp2[i][k]+dp2[k+1][j])<mins?dp2[i][k]+dp2[k+1][j]:mins; } dp1[i][j]=maxs+sum[j]-sum[i-1]; dp2[i][j]=mins+sum[j]-sum[i-1]; } } /* for (i=1;i<=n;i++) { for (j=i;j<i+n;j++) { printf("%d ",dp2[i][j]); } printf("\n"); }*/ for (i=1,maxs=0,mins=INF;i<=n;i++) { maxs=dp1[i][i+n-1]>maxs?dp1[i][i+n-1]:maxs; mins=dp2[i][i+n-1]<mins?dp2[i][i+n-1]:mins; } printf("%d\n%d\n",mins,maxs); } return 0; }