hdu2829
题目大意:还是不说了,看原文链接吧。
这类题目可单独作为一类四边形不等式,因为一般题目讨论的是一个最优解,这里是对应着用最优解集。
其核心还是解的单调性s[i][j-1] <= s[i][j] <= s[i+1][j]。难点就是选取一个什么量s[i][j]来描述一个解集!
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int N = 1010; 6 int dp[N][N],s[N][N]; 7 int val[N],sv[N],dv[N]; 8 const int infinity=(-1)^(1<<31); 9 int S(int i,int j){ // i到j作为一段 10 return dv[i]-dv[j]-(sv[i]-sv[j])*sv[j+1]; 11 } 12 int DP(int n,int m){ 13 if(m >= n-1) return 0; 14 m++; 15 for(int i=1;i<=n;i++) dp[i][1]=S(i,n),s[i][1]=n; 16 for(int mm=2;mm<=m;mm++){ 17 int maxi=n-mm+1,tmp; 18 dp[maxi][mm]=0; s[maxi][mm]=maxi; 19 //printf("dp[%d][%d] = %d, s = %d\n",maxi,mm,dp[maxi][mm],s[maxi][mm]); 20 for(int i=maxi-1;i>0;i--){ 21 dp[i][mm]=infinity; 22 for(int k=i;k<=s[i+1][mm];k++) 23 if((tmp=dp[k+1][mm-1]+S(i,k)) < dp[i][mm]) 24 dp[i][mm]=tmp,s[i][mm]=k; 25 //printf("dp[%d][%d] = %d, s = %d\n",i,mm,dp[i][mm],s[i][mm]); 26 } 27 } 28 return dp[1][m]; 29 } 30 int main() 31 { 32 int n,m; 33 while(scanf("%d%d",&n,&m)){ 34 if(n<=0 && m<=0) break; 35 for(int i=1;i<=n;i++) 36 scanf("%d",&val[i]); 37 sv[n+1]=0,dv[n+1]=0; 38 for(int i=n;i>0;i--) 39 dv[i]=sv[i+1]*val[i]+dv[i+1],sv[i]=sv[i+1]+val[i];// printf("dv[i] = %d, sv[i] = %d\n",dv[i],sv[i]); 40 //int i,j; while(cin>>i>>j) printf("sij = %d\n",S(i,j)); 41 printf("%d\n",DP(n,m)); 42 } 43 return 0; 44 }