码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 4244 括号序列dp

时间:2018-10-22 20:37:14      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:小故事   左右   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

标签:小故事   左右   sdi   int   void   序列   return   std   git   

原文地址:https://www.cnblogs.com/asdic/p/9831359.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!