標籤:小故事 左右 sdi int void 序列 return std git
將各種情況繞環等看作括弧序列,括弧內的地區上下都需要累加答案,左右也是
f[i][j] 代表 前i個車站已經處理完的有j個左括弧的最小權值
我們可以發現,更新的來源來自於 i-1, 和 i
將上 描述為L1,L2, 下描述為R1,R2,所以可以通過括弧內的沿伸以及左右括弧的答案更新狀態
具體代碼如下
#include<bits/stdc++.h>#define rep(i,x,y) for(register int i=x;i<=y;i++)#define dec(i,x,y) for(register int i=x;i>=y;i--)using namespace std;inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f;} namespace zkc{ const int N=3050; int n,T,L1[N],L2[N],R1[N],R2[N],f[N][N]; inline void work(){ n=read(),T=read(); rep(i,1,n) R1[i]=read(),L1[i]=read(),L2[i]=read(),R2[i]=read(); memset(f,0x3f,sizeof f);f[0][0]=0; rep(i,1,n){ //from i-1 zhuan‘yi rep(j,0,n){ if(j){//來自於i-1的轉移 f[i][j]=min(f[i][j],f[i-1][j-1]+(j-1)*2*T+L1[i]+L2[i]); //第一個轉移需要保證j的原因是其由左邊j-1轉移而來(
f[i][j]=min(f[i][j],f[i-1][j]+j*2*T+L2[i]+R2[i]);}
//由於此條轉移走的是下路,也就是已經到了下班狀態,至少有一次向下的左括弧還沒有被匹配 //下班路上取郵戳
f[i][j]=min(f[i][j],f[i-1][j]+j*2*T+L1[i]+R1[i]);
//上班路上取郵戳 f[i][j]=min(f[i][j],f[i-1][j+1]+(j+1)*2*T+R1[i]+R2[i]); //匹配右括弧
} rep(j,1,n) f[i][j]=min(f[i][j],f[i][j-1]+L1[i]+L2[i]); //自己和自己玩的小故事
dec(j,n-1,0) f[i][j]=min(f[i][j],f[i][j+1]+R1[i]+R2[i]); //自己和自己玩的小故事2
} printf("%d\n",f[n][0]+(n+1)*T);return; }}int main(){ zkc::work(); return 0;}
完結撒花
不過話說回來,其實還有許多不太明白的轉移順序問題,日後慢慢理解哈
bzoj 4244 括弧序列dp