【Bzoj1187】神奇游乐园(插头DP)

Description

题意给定一个矩阵,每个格子有权值,在[-1000.1000]内,求一条回路使得回路经过权值和最大,每个格子最多经过一次

2≤n≤100,2≤m≤6

Code

#include <cstdio>
#include <algorithm>
#define N 10
#define Inf 0x7fffffff
using namespace std;

int A[N],now,op[N],k[N],L[N],Ans=-Inf;
int n,m,g[110][N],dp[2][20000],q[2][20000],t[2];

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

void push(int x,int y){
    if(dp[now^1][x]==-Inf) q[now^1][++t[now^1]]=x;
    dp[now^1][x]=max(dp[now^1][x],y);
}

void clear(){
    for(int i=1;i<=t[now];++i) dp[now][q[now][i]]=-Inf;
    t[now]=0;
    now^=1;
}

void f(int S){
    int tp=0;
    for(int i=0;i<=m;++i){
        k[i]=S&3,S>>=2;//
        if(k[i]==1) L[++tp]=i;
        else if(k[i]==2) op[op[i]=L[tp--]]=i;
    }
}

void bfs(int x,int y){
    clear();
    for(int i=1;i<=t[now];++i){
        int S=q[now][i];
        f(S);
        int l=k[y-1],r=k[y],upd=dp[now][S]+g[x][y];
        if(!l&&!r){
            push(S,upd-g[x][y]);
            push(S+A[y-1]+(A[y]<<1),upd);
        }else if(l&&r){
            int tS=S-l*A[y-1]-r*A[y];
            if(l==2&&r==1) push(tS,upd);
            else if(l==1&&r==1) push(tS-A[op[y]],upd);
            else if(l==2&&r==2) push(tS+A[op[y-1]],upd);
            else if(!tS) Ans=max(Ans,upd);
        }
        else{
            push(S,upd);
            push(S-l*A[y-1]-r*A[y]+l*A[y]+r*A[y-1],upd);
        }
    }
}

int main(){
    A[0]=1;for(int i=1;i<N;++i)A[i]=A[i-1]<<2;//四进制
    for(int i=0;i<2;++i)for(int j=0;j<20000;++j)dp[i][j]=-Inf;
    n=read(),m=read();
    for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)g[i][j]=read();
    push(0,0);
    for(int i=1;i<=n;++i){
        clear();
        for(int j=1;j<=t[now];++j) if(q[now][j]<A[m]) push(q[now][j]<<2,dp[now][q[now][j]]);
        for(int j=1;j<=m;++j) bfs(i,j);
    }
    printf("%d\n",Ans);
    return 0;
}

原文地址:https://www.cnblogs.com/void-f/p/8277850.html

时间: 2024-10-28 11:04:30

【Bzoj1187】神奇游乐园(插头DP)的相关文章

【BZOJ1187】[HNOI2007]神奇游乐园 插头DP

[BZOJ1187][HNOI2007]神奇游乐园 Description 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这是一个游乐场,专为旅途中疲惫的人设计.娱乐场可以看成是一块大小为n×m的区域,且这个n×m的区域被分成n×m个小格子,每个小格子中就有一个娱乐项目.然而,小P并不喜欢其中的所有娱乐项目,于是,他给每个项目一个满意度.满意度为正时表示小P喜欢这个项目,值越大表示越喜欢.为负时表示他不喜欢

bzoj 1187: [HNOI2007]神奇游乐园 插头dp

1187: [HNOI2007]神奇游乐园 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 668  Solved: 337[Submit][Status][Discuss] Description 经 历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这是一个游 乐场,专为旅途中疲惫的人设计.娱乐场可以看成是一块大小为n×m的区域,且这个n×m的区域被分成n×m个

【插头DP】BZOJ1187- [HNOI2007]神奇游乐园

[题目大意] 在n*m的网格中选一条回路,使权值和最大. [思路] 和之前裸的插头DP差不多,只不过现在回路不需要经过所有的格子.所以有以下几个注意点(具体看注释): (1)left和up插头相等的时候,直接更新答案; (2)left和up插头不存在的时候,还要考虑当前格子不取的情况. orz写了半天,感觉被掏空.jpg 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int MA

[入门向选讲] 插头DP:从零概念到入门 (例题:HDU1693 COGS1283 BZOJ2310 BZOJ2331)

转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/7326874.html 最近搞了一下插头DP的基础知识……这真的是一种很锻炼人的题型…… 每一道题的状态都不一样,并且有不少的分类讨论,让插头DP十分锻炼思维的全面性和严谨性. 下面我们一起来学习插头DP的内容吧! 插头DP主要用来处理一系列基于连通性状态压缩的动态规划问题,处理的具体问题有很多种,并且一般数据规模较小. 由于棋盘有很特殊的结构,使得它可以与“连通性”有很强的联系,因此插头DP最常见的应用要数

【BZOJ 1187】 [HNOI2007]神奇游乐园

1187: [HNOI2007]神奇游乐园 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 706 Solved: 358 [Submit][Status][Discuss] Description 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这是一个游乐场,专为旅途中疲惫的人设计.娱乐场可以看成是一块大小为n×m的区域,且这个n×m的区域被分成n×m个小格

【BZOJ2310】ParkII 插头DP

[BZOJ2310]ParkII Description Hnoi2007-Day1有一道题目 Park:给你一个 m * n 的矩阵,每个矩阵内有个权值V(i,j) (可能为负数),要求找一条回路,使得每个点最多经过一次,并且经过的点权值之和最大,想必大家印象深刻吧. 无聊的小 C 同学把这个问题稍微改了一下:要求找一条路径,使得每个点最多经过一次,并且点权值之和最大,如果你跟小 C 一样无聊,就麻烦做一下这个题目吧. Input 第一行 m, n,接下来 m行每行 n 个数即. V( i,j

「总结」插头$dp$

集中做完了插头$dp$ 写一下题解. 一开始学的时候还是挺蒙的. 不过后来站在轮廓线$dp$的角度上来看就简单多了. 其实就是一种联通性$dp$,只不过情况比较多而已了. 本来转移方式有两种.逐行和逐格转移. 不过逐行转移因为分类太多所以被舍弃了. 一般的插头$dp$采用逐格转移. 插头表示已经进入当前格子的状态,而并不是将要进入的状态. 状态的表示方式常见的有两种:最小表示法和括号表示法. 括号表示法不如说是广义括号表示法的特殊一种情况,每个插头也就是左右括号就是表示两个相匹配的回路部分,而最

初探插头dp

开学那个月学了点新东西,不知道还记不记得了,mark一下 感觉cdq的论文讲的很详细 题主要跟着kuangbin巨做了几道基础的 http://www.cnblogs.com/kuangbin/archive/2012/10/02/2710343.html 还有几道没做,留着坑 感觉广义括号表示法虽然神奇,但一般最小表示法就够用了吧,感觉最小表示法更直观一点 hdu1693 1 #include<cstdio> 2 #include<iostream> 3 #include<

插头dp题表(已完成)

bzoj1814: Ural 1519 Formula 1 bzoj3125: CITY bzoj1210: [HNOI2004]邮递员 bzoj2331: [SCOI2011]地板 bzoj1187: [HNOI2007]神奇游乐园 bzoj2310: ParkII 原文地址:https://www.cnblogs.com/TSHugh/p/8179245.html

【learning】插头dp

问题描述 一种网格棋盘上的回路(路径也可以)数量统计之类的问题,也可以是求最优值之类的可以考虑dp求解的问题 具体解法 一些必须前置的东西 首先是一些概念的引入: 1.插头:既然是插头dp那肯定要先说说插头是啥,插头其实可以理解为每个格子的路经的走向,有以下几种情况: 2.轮廓线:就是下图中蓝色的那条东西,我们在转移的时候采用状态压缩的方式记录轮廓线的..轮廓,然后一个一个格子来转移 与一般的dp不同,插头dp是基于轮廓线的dp而不是基于格子的dp,这是很重要的一点 具体什么意思呢?就是说我们在