HDU 2829 Lawrence

_(:3」∠)_

dp[i][j]:前i个分j组的最小值

cost[i][j]:i到j为一组的值

sum[i]:前i个的值的总和

dp[i][j]=min{dp[k][j-1]+cost[k+1][i]}

cost[k+1][i]=cost[1][i]-cost[1][k]-sum[k]*(sum[i]-sum[k])=cost[i]-cost[k]+sum[k]*sum[k]-sum[k]*sum[i]

令y=dp[k][j-1]-cost[k]+sum[k]*sum[k]

则dp[i][j]=min{y+cost[i]-sum[k]*sum[i]}

sum[i]为斜率

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<iostream>
 6 #include<queue>
 7 #include<stack>
 8 #include<cmath>
 9 #include<map>
10 #define BUG printf("hehe\n")
11 #define INF 0x3f3f3f3f
12 #define ll long long
13 using namespace std;
14 
15 int cost[1010],sum[1010];
16 int dp[1010][1010],q[1010];
17 int n,m,head,tail;
18 
19 int dx(int a,int b)
20 {
21     return sum[a]-sum[b];
22 }
23 
24 int dy(int x,int a,int b)
25 {
26     return dp[a][x]-cost[a]+sum[a]*sum[a]-(dp[b][x]-cost[b]+sum[b]*sum[b]);
27 }
28 
29 int main()
30 {
31     int t;
32     while(scanf("%d%d",&n,&m)&&(n|m)) {
33         sum[0]=0;
34         cost[0]=0;
35         for(int i=1;i<=n;++i) {
36             scanf("%d",&t);
37             sum[i]=sum[i-1]+t;
38             cost[i]=cost[i-1]+t*sum[i-1];
39         }
40         for(int i=1;i<=n;++i)
41             dp[i][1]=cost[i];
42 
43         for(int j=2;j<=m+1;++j) {
44             head=0,tail=-1;
45             q[++tail]=j-1;
46             for(int i=j;i<=n;++i) {
47                 while(head<tail&&(dy(j-1,q[head+1],q[head])<sum[i]*dx(q[head+1],q[head]))) ++head;
48                 dp[i][j]=dp[q[head]][j-1]-cost[q[head]]+sum[q[head]]*sum[q[head]]+
49                             cost[i]-sum[i]*sum[q[head]];
50                 while(head<tail&&(dy(j-1,i,q[tail])*dx(q[tail],q[tail-1])
51                       <=dy(j-1,q[tail],q[tail-1])*dx(i,q[tail]))) --tail;
52                 q[++tail]=i;
53             }
54         }
55         printf("%d\n",dp[n][m+1]);
56     }
57 }

 

 

 

四边形优化:

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iostream>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
#define BUG printf("hehe\n")
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;

int cost[1010][1010],sum[1010];
int s[1010][1010];
int dp[1010][1010];
int a[1010];
int n,m,head,tail;

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)&&(n|m)) {
        sum[0]=0;
        for(int i=1;i<=n;++i) {
            scanf("%d",a+i);
            sum[i]=sum[i-1]+a[i];
        }
        memset(cost,0,sizeof cost);
        for(int i=1;i<=n;++i)
        for(int j=i+1;j<=n;++j) {
            cost[i][j]=cost[i][j-1]+a[j]*(sum[j-1]-sum[i-1]);
        }
        for(int i=0;i<=n;++i) {
            dp[i][1]=cost[1][i];
            s[i][1]=1;
            s[n+1][i]=n-1;
        }
        for(int j=2;j<=m+1;++j) {
            for(int i=n;i>=1;--i) {
                dp[i][j]=INF;
                for(int k=s[i][j-1];k<=s[i+1][j];++k) {
                    if(dp[k][j-1]+cost[k+1][i]<dp[i][j]) {
                        s[i][j]=k;
                        dp[i][j]=dp[k][j-1]+cost[k+1][i];
                    }
                }
            }
        }
        printf("%d\n",dp[n][m+1]);
    }
}

 

posted @ 2014-04-04 20:59  MoriMiya  Views(156)  Comments(0Edit  收藏  举报