hdu5550 Game Rooms dp

hdu5550 Game Rooms  dp

調了一下午的bug終於過了。。。思路是沒錯的,可是因爲用了刷表法思考,因此只考慮刷表以後的狀態,沒有注意刷表前的最初狀態,因而調了一下午的bug終於找出來了。。。c++

dp[i][j][k] 表示 前i個,最後一個k的位置爲j ( k取0,1,j<i ) 的總花費。ide

轉移有兩個,即第i+1個位置爲0或者1:spa

dp[i+1][j][k]=min(dp[i+1][j][k] , dp[i][j][k]+a[i+1][k]*(i+1-j)) code

dp[i+1][i][!k]=min(dp[i+1][i][!k],  dp[i][j][k]+L(j+1,m,j,k)+L(m+1,i,i+1,k)-L(j+1,i,j,k)+a[i+1][!k])  (m爲j和i+1的中點)blog

這裏有一點須要特別注意的是:ci

因爲過程當中不存在全0或者全1的狀況(0000或1111),因此000001不可能由00000推出來,這裏須要預處理出全部的00001和111110,也就是將dp[i][i-1][k]的初值設爲000001或1111110的值。it

另外還有一點,計算L(l,r,x,k)能夠維護一個sum(i*a[i])和sum(a[i])來實現o(1)的計算。event

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
const int maxn=4010;
const int INF=1<<29;

int n;
ll a[maxn][2],s[maxn][2],fs[maxn][2];
ll si[maxn][2],fsi[maxn][2];
ll dp[2][maxn][2];

ll Pre(int l,int r,int x,int k)
{
    if(l>r) return 0;
    return (si[r][k]-si[l-1][k])-(s[r][k]-s[l-1][k])*x;
}

ll Suf(int l,int r,int x,int k)
{
    if(l>r) return 0;
    return (fsi[l][k]-fsi[r+1][k])-(fs[l][k]-fs[r+1][k])*(n-x+1);
}

ll L(int l,int r,int x,int k)
{
    if(l>r) return 0;
    if(x<=l) return Pre(l,r,x,k);
    if(x>=r) return Suf(l,r,x,k);
    return Suf(l,x-1,x,k)+Pre(x+1,r,x,k);
}

int main()
{
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    int T;cin>>T;int casen=1;
    while(T--){
        scanf("%d",&n);
        REP(i,1,n) scanf("%I64d%I64d",&a[i][0],&a[i][1]);
        //out();
        s[0][0]=s[0][1]=0;
        si[0][0]=si[0][1]=0;
        REP(i,1,n){
            s[i][0]=s[i-1][0]+a[i][0];
            s[i][1]=s[i-1][1]+a[i][1];
            si[i][0]=si[i-1][0]+a[i][0]*i;
            si[i][1]=si[i-1][1]+a[i][1]*i;
        }
        fs[n+1][0]=fs[n+1][1]=0;
        fsi[n+1][0]=fsi[n+1][1]=0;
        for(int i=n;i>=1;i--){
            fs[i][0]=fs[i+1][0]+a[i][0];
            fs[i][1]=fs[i+1][1]+a[i][1];
            fsi[i][0]=fsi[i+1][0]+a[i][0]*(n-i+1);
            fsi[i][1]=fsi[i+1][1]+a[i][1]*(n-i+1);
        }
        MS0(dp);
        ll MAX=1LL<<60;
        memset(dp,0x3f3f3f,sizeof(dp));
        ll ans=MAX;
        dp[2%2][1][0]=a[1][1]+a[2][0];
        dp[2%2][1][1]=a[1][0]+a[2][1];
        REP(i,2,n-1){
            REP(j,1,i){
                REP(k,0,1){
                    dp[(i+1)%2][j][k]=L(1,j,j+1,!k)+L(j+1,i+1,j,k);
                }
            }
            REP(j,1,i-1){
                REP(k,0,1){
                    dp[(i+1)%2][j][k]=min(dp[(i+1)%2][j][k],dp[i%2][j][k]+a[i+1][k]*(i+1-j));
                    int m=(j+i+1)>>1;
                    dp[(i+1)%2][i][!k]=min(dp[(i+1)%2][i][!k],dp[i%2][j][k]+L(j+1,m,j,k)+L(m+1,i,i+1,k)-L(j+1,i,j,k)+a[i+1][!k]);
                }
            }
        }
        REP(i,1,n-1){
            //printf("dp[%d][%d][0]=%I64d dp[%d][%d][1]=%I64d\n",n,i,dp[n%2][i][0],n,i,dp[n%2][i][1]);
            ans=min(ans,dp[n%2][i][0]);
            ans=min(ans,dp[n%2][i][1]);
        }
        printf("Case #%d: %I64d\n",casen++,ans);
    }
    return 0;
}
View Code
相關文章
相關標籤/搜索