Codeforces 375C - Circling Round Treasures(状压 dp+最短路转移)
注意到这题中宝藏 \(+\) 炸弹个数最多只有 \(8\) 个,故考虑状压,设 \(dp[x][y][S]\) 表示当前坐标为 \((x,y)\),有且仅有 \(S\) 当中的物品被包围在凸多边形内部所走过的最少步数。
考虑转移,枚举与 \((x,y)\) 相邻的点 \((x',y')\)。但是 \(S\) 的变化可能有些棘手。这里有一个结论,对于某一点 \((x,y)\),任意引出一条射线,如果它与多边形有奇数个交点,那么 \((x,y)\) 就在多边形内部。由于这里引出的射线可以沿任何方向,那么我们不妨统一假设射线的方向都是向右,故这里的状态 \(S\) 就可以理解为:满足 \((x,y)\) 向右引出的射线与多边形交点个数为奇数的点的集合。
这样一来状态是倒搞明白了,但是直接这样转移还是可能会出现一些问题,因为有可能我们是从某个点 \((x,y)\) 向右走到 \((x,y+1)\),而对于某个横坐标也为 \(x\) 的点 \((x,y')\),它向右引出的射线与多边形出现了重合的情况,进而就不好计算交点个数。不过这个问题很容易解决,因为行走的路径不会经过宝藏/炸弹,故横向的线段并不会影响交点个数,于是只需计算纵向的线段就行了。
但是这样还是会出现问题。比方说下图,对于点 \(A\) 向右引出的橙色射线,如果按照我们的判断其与多边形有两个交点 \(B,C\),但如果我们把横向的线段去掉,将两个纵向线段拼在一起,就会发现有用的交点只有 \(1\) 个。这个问题也异常容易解决,考虑将每条纵向的线段看作一个上开下闭的线段,当从 \((x,y)\) 走到 \((x+1,y)\) 时只改变满足 \(x'=x+1,y'<y\) 的点 \((x',y')\) 的状态;当从 \((x,y)\) 走到 \((x-1,y)\) 时只改变满足 \(x'=x,y'<y\) 的点 \((x',y')\) 的状态。这样一来就可以避免这个问题了。
最短路转移即可。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc((x%10)+'0');}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=20;
const int MAXP=256;
const int MAXM=8;
const int INF=0x3f3f3f3f;
const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};
int n,m,sx,sy;char s[MAXN+3][MAXN+3];
int dp[MAXN+2][MAXN+2][MAXP+3];
int px[MAXM+2],py[MAXM+2],a[MAXM+2],c1=0,c2=0;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(s[i][j]=='S') sx=i,sy=j;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(isdigit(s[i][j])){
px[s[i][j]^48]=i;py[s[i][j]^48]=j;c1++;
} c2=c1;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(s[i][j]=='B') px[++c2]=i,py[c2]=j;
for(int i=1;i<=c1;i++) scanf("%d",&a[i]);
memset(dp,63,sizeof(dp));dp[sx][sy][0]=0;
queue<pair<pii,int> > q;q.push(mp(mp(sx,sy),0));
while(!q.empty()){
pair<pii,int> p=q.front();q.pop();
int x=p.fi.fi,y=p.fi.se,msk=p.se;
// printf("%d %d %d %d\n",x,y,msk,dp[x][y][msk]);
for(int i=0;i<4;i++){
int nx=x+dx[i],ny=y+dy[i];
if(nx<1||nx>n||ny<1||ny>m) continue;
if(s[nx][ny]!='.'&&s[nx][ny]!='S') continue;
int nmsk=msk;
for(int j=1;j<=c2;j++) if((!(px[j]^x)&&!(i^2)||!(px[j]^nx)&&!i)&&py[j]<ny)
nmsk^=1<<j-1;
if(dp[nx][ny][nmsk]==INF){
dp[nx][ny][nmsk]=dp[x][y][msk]+1;
q.push(mp(mp(nx,ny),nmsk));
}
}
}
int ans=-INF;
for(int i=0;i<(1<<c1);i++) if(dp[sx][sy][i]!=INF){
int sum=0;
for(int j=0;j<c1;j++) sum+=a[j+1]*(i>>j&1);
chkmax(ans,sum-dp[sx][sy][i]);
} printf("%d\n",ans);
return 0;
}
Codeforces 375C - Circling Round Treasures(状压 dp+最短路转移)的更多相关文章
- Codeforces 375C Circling Round Treasures - 最短路 - 射线法 - 位运算
You have a map as a rectangle table. Each cell of the table is either an obstacle, or a treasure wit ...
- 旅游(CSUST省赛选拔赛2+状压dp+最短路)
题目链接:http://csustacm.com:4803/problem/1016 题目: 思路:状压dp+最短路,比赛的时候有想到状压dp,但是最短路部分写挫了,然后就卡死了,对不起出题人~dis ...
- CF 375C Circling Round Treasures [DP(spfa) 状压 射线法]
C - Circling Round Treasures 题意: 在一个$n*m$的地图上,有一些障碍,还有a个宝箱和b个炸弹.你从(sx,sy)出发,走四连通的格子.你需要走一条闭合的路径,可以自交 ...
- Codeforces 453B Little Pony and Harmony Chest:状压dp【记录转移路径】
题目链接:http://codeforces.com/problemset/problem/453/B 题意: 给你一个长度为n的数列a,让你构造一个长度为n的数列b. 在保证b中任意两数gcd都为1 ...
- codeforces 8C. Looking for Order 状压dp
题目链接 给n个物品的坐标, 和一个包裹的位置, 包裹不能移动. 每次最多可以拿两个物品, 然后将它们放到包里, 求将所有物品放到包里所需走的最小路程. 直接状压dp就好了. #include < ...
- Codeforces 429C Guess the Tree(状压DP+贪心)
吐槽:这道题真心坑...做了一整天,我太蒻了... 题意 构造一棵 $ n $ 个节点的树,要求满足以下条件: 每个非叶子节点至少包含2个儿子: 以节点 $ i $ 为根的子树中必须包含 $ c_i ...
- Codeforces 895C Square Subsets(状压DP 或 异或线性基)
题目链接 Square Subsets 这是白书原题啊 先考虑状压DP的做法 $2$到$70$总共$19$个质数,所以考虑状态压缩. 因为数据范围是$70$,那么我们统计出$2$到$70$的每个数的 ...
- 【题解】codeforces 8c Looking for Order 状压dp
题目描述 Lena喜欢秩序井然的生活.一天,她要去上大学了.突然,她发现整个房间乱糟糟的--她的手提包里的物品都散落在了地上.她想把所有的物品都放回她的手提包.但是,这里有一点问题:她一次最多只能拿两 ...
- Codeforces 895C Square Subsets:状压dp【组合数结论】
题目链接:http://codeforces.com/problemset/problem/895/C 题意: 给你n个数a[i].(n <= 10^5, 1 <= a[i] <= ...
随机推荐
- Flask聚合函数(基本聚合函数、分组聚合函数、去重聚合函数))
Flask聚合函数 1.基本聚合函数(sun/count/max/min/avg) 使用聚合函数先导入:from sqlalchemy import func 使用方法: sun():func.sum ...
- 《JavaScript DOM编程艺术》:+= 相加之后再赋值
第2章 第20页 += var year = 2010; var message = "The year is"; message += year; message += yea ...
- Java版人脸检测详解上篇:运行环境的Docker镜像(CentOS+JDK+OpenCV)
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Jupyter Notebook配置多个kernel
Jupyter Notebook配置多个kernel 前言: 在anaconda下配置了多个环境,而Jupiter Notebook只是安装在base环境下,为了能在Jupiter Notebook中 ...
- spring源码分析(二)- 容器基础
1.基本用法 用过Spring的都知道,bean是Spring中最基础也是最核心的.首先看一个简单的例子. 一个类和一个配置文件 package bean; public class MyBean { ...
- createContext 你用对了吗?
目录 前言 性能问题的根源 问题1(整体重复渲染):Provider组件包裹的子组件全部渲染 问题2(局部重复渲染):使用useContext导致组件渲染 解决方案 解决问题1 解决问题2 参考 前言 ...
- 极速上手 VUE 3—v-model 的使用变化
本篇文章主要介绍 v-model 在 Vue2 和 Vue3 中使用变化. 一.Vue2 中 v-model 的使用 v-model 是语法糖,本质还是父子组件间的通信.父子组件通信时有两种方式: 父 ...
- nodejs:使用puppeteer在服务器中构建一个获取电影电视剧剧集的接口
首先我们看下数据来源: 来源于这个网站:https://z1.m1907.cn/ 可以说这个网站上能找到很多你想看的很多电影或电视剧,最重要的是很多电影电视剧在别的网站是收费的,但是在这里看是免费的, ...
- VNC服务器的搭建(带图形化支持)
环境:centos7.6最小化安装 图形化支持 如果希望安装简单的图形支持的话,仅包含gnome的最最最最基础的包的话可以使用以下命令 yum groups install "X Windo ...
- 13-Semi-supervised Learning
半监督学习(semi-supervised learning) 1.introduction 2.Semi-supervised Learning for Generative Model 3.Low ...