做法:第一个双塔DP,或许使Codeforces Beta Round #90, problem: (C) Education Reform DP 吧.
和一般的双塔DP 差不多,记录两个机器工作时间的差值即可,可是有一点要注意的是每一个任务只能在上一个任务正在完成或已经完成的时候开始,所以当新任务在高一点的塔上做时,低塔的高度也要增加(权当是空闲时间吧,因为那段时间I任务还没有开始I+1也休想开始).
#include<cstdio> #include<cstring> const int eps=100000000; const int LMT=202; const int offset=100; int dp[LMT][LMT],ta[LMT],tb[LMT],ans; inline int max(int a,int b) { return a>b?a:b; } inline int min(int a,int b) { return a<b?a:b; } void init(void) { int i,j; for(i=0;i<LMT;i++) for(j=0;j<LMT;j++)dp[i][j]=eps; dp[0][offset]=0; ans=eps; } int main(void) { int T,n,i,d,j; scanf("%d",&T); while(T--) { init(); scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d%d",&ta[i],&tb[i]); for(i=1;i<=n;i++) for(d=-offset;d<=offset;d++) if(dp[i-1][offset+d]!=eps) { j=offset+d; if(d<=0) { dp[i][offset-tb[i]]=min(dp[i][offset-tb[i]],dp[i-1][j]+tb[i]); dp[i][j+ta[i]]=min(dp[i][j+ta[i]],dp[i-1][j]+max(0,d+ta[i])); } else { dp[i][offset+ta[i]]=min(dp[i][offset+ta[i]],dp[i-1][j]+ta[i]); dp[i][j-tb[i]]=min(dp[i][j-tb[i]],dp[i-1][j]+max(0,tb[i]-d)); } } for(i=0;i<=(offset<<1);i++) ans=min(ans,dp[n][i]); printf("%d\n",ans); } return 0; }