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 }
View Code

 

posted on 2013-11-24 14:44  男神发量  阅读(325)  评论(0编辑  收藏  举报