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

 

你可能感兴趣的:(HDU)