hdu5550 Game Rooms dp
hdu5550 Game Rooms dp
调了一下午的bug终于过了。。。思路是没错的,但是由于用了刷表法思考,所以只考虑刷表之后的状态,没有注意刷表前的最初状态,于是调了一下午的bug终于找出来了。。。
dp[i][j][k] 表示 前i个,最后一个k的位置为j ( k取0,1,j<i ) 的总花费。
转移有两个,即第i+1个位置为0或者1:
dp[i+1][j][k]=min(dp[i+1][j][k] , dp[i][j][k]+a[i+1][k]*(i+1-j))
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的中点)
这里有一点需要特别注意的是:
由于过程中不存在全0或者全1的情况(0000或1111),所以000001不可能由00000推出来,这里需要预处理出所有的00001和111110,也就是将dp[i][i-1][k]的初值设为000001或1111110的值。
另外还有一点,计算L(l,r,x,k)可以维护一个sum(i*a[i])和sum(a[i])来实现o(1)的计算。
#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; }
没有AC不了的题,只有不努力的ACMER!