P2937 [USACO09JAN]Laserphones S
题意描述
学过物理的同学都知道这种镜子是可以把光线旋转 90 度的。
那么显然就是要求添加镜子的最小个数。
貌似题目漏了一句就是题目保证有解的情况。
算法分析
其实可以联想到之前的分层图最短路。(不要问我为什么)
建立4层相同的图。层内只能向着某个方向走,因此在可以走的地方建权值为0的边。
层间实现转弯,两两建权值为1的边,表示可以转弯,但有花费。
最后从每一层的起点到每一层的终点跑最短路,统计花费就行了。
代码实现
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define N 510
#define INF 0x3f3f3f3f
using namespace std;
int n,m,sx,sy,ex,ey,dis[N*N<<2],head[N*N<<2],cnt=0;
int dx[5]={0,1,-1,0,0};
int dy[5]={0,0,0,1,-1};
bool vis[N*N<<2];
char a[N][N];
struct Edge{
int nxt,to,val;
}ed[N*N<<3];
int read(){
int x=0,f=1;char c=getchar();
while(c<'0' || c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' && c<='9') x=x*10+c-48,c=getchar();
return x*f;
}
void init(){
m=read(),n=read();
char c;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>c;
if(c=='C'){
if(!sx) sx=i,sy=j;
else ex=i,ey=j;
}
a[i][j]=c;
}
return;
}
int ID(int t,int x,int y){return (t-1)*n*m+(x-1)*m+y;}
void add(int u,int v,int w){
ed[++cnt].nxt=head[u];
ed[cnt].to=v;
ed[cnt].val=w;
head[u]=cnt;
return;
}
void build(){
for(int t=1;t<=4;t++)
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
int fx=i+dx[t];
int fy=j+dy[t];
if(fx<1 || fx>n || fy<1 || fy>m || a[fx][fy]=='*' || a[i][j]=='*') continue;
add(ID(t,i,j),ID(t,fx,fy),0);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(a[i][j]=='*') continue;
for(int u=1;u<=4;u++)
for(int v=1;v<=4;v++)
if(u^v) add(ID(u,i,j),ID(v,i,j),1);
}
return;
}
int ans=INF;
priority_queue<pair<int,int> >q;
void dij(int s){
while(!q.empty()) q.pop();
memset(dis,0x3f,sizeof(dis));
memset(vis,false,sizeof(vis));
dis[s]=0;q.push(make_pair(0,s));
while(!q.empty()){
int u=q.top().second;q.pop();
if(vis[u]) continue;
vis[u]=true;
for(int i=head[u];i;i=ed[i].nxt){
int v=ed[i].to,w=ed[i].val;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push(make_pair(-dis[v],v));
}
}
}
return;
}
void work(){
for(int i=1;i<=4;i++){
dij(ID(i,sx,sy));
for(int j=1;j<=4;j++)
ans=min(ans,dis[ID(j,ex,ey)]);
}
return;
}
int main(){
init();
build();
work();
printf("%d\n",ans);
return 0;
}
完结撒花
P2937 [USACO09JAN]Laserphones S的更多相关文章
- 洛谷 题解 P2937 【[USACO09JAN]激光电话Laserphones】
看到这题,一下就想到了爆搜.(不过这题输入也是够坑的) 单纯的搜索肯定是会超时的,所以这里需要考虑一些剪枝. 我们令bin[i][j][k]为在第i行j列时,方向为k的最小镜子数,若当时的镜子数已大于 ...
- luogu P2934 [USACO09JAN]安全出行Safe Travel
题目链接 luogu P2934 [USACO09JAN]安全出行Safe Travel 题解 对于不在最短路树上的边(x, y) 1 | | t / \ / \ x-----y 考虑这样一种形态的图 ...
- 2018.07.06 洛谷P2936 [USACO09JAN]全流Total Flow(最大流)
P2936 [USACO09JAN]全流Total Flow 题目描述 Farmer John always wants his cows to have enough water and thus ...
- P2934 [USACO09JAN]安全出行Safe Travel
P2934 [USACO09JAN]安全出行Safe Travel https://www.luogu.org/problemnew/show/P2934 分析: 建出最短路树,然后考虑一条非树边u, ...
- 洛谷——P2935 [USACO09JAN]最好的地方Best Spot
P2935 [USACO09JAN]最好的地方Best Spot 题目描述 Bessie, always wishing to optimize her life, has realized that ...
- $P2935 [USACO09JAN]最好的地方Best Spot$
P2935 [USACO09JAN]最好的地方Best Spot Floyd的水题(黄题) 海星. 这可能是我第一道发的Floyd的博客 inline void Floyd(){ ;k<=n;k ...
- 洛谷 P2932 [USACO09JAN]地震造成的破坏Earthquake Damage
P2932 [USACO09JAN]地震造成的破坏Earthquake Damage 题目描述 Wisconsin has had an earthquake that has struck Farm ...
- bzoj3393 [Usaco2009 Jan]Laserphones 激光通讯
Description Input 第1行输入w和H,之后W行H列输入地图,图上符号意义如题目描述. Output 最少的对角镜数量. Sample Input 7 8 ....... ...... ...
- ●洛谷P2934 [USACO09JAN]安全出行Safe Travel
题链: https://www.luogu.org/problemnew/show/P2934 题解: 最短路(树),可并堆(左偏堆),并查集. 个人感觉很好的一个题. 由于题目已经明确说明:从1点到 ...
随机推荐
- pycharm 配置 github
今天突然想把自己的代码上传到github上去,然后就研究了下pycharm的配置. 首先呢,你得有个github的账号,然后建立一个项目. 然后打开pycharm,选择file->Setting ...
- QT博客:QT学习之路
http://www.qter.org/thread-629-1-1.html
- ATMEGA的SPI总线 - 第2部分
参考: 1.https://www.yiboard.com/thread-783-1-1.html 2.https://mansfield-devine.com/speculatrix/2018/01 ...
- RHSA-2018:1200-重要: patch 安全更新(代码执行)
[root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 修复命令: 使用root账号登陆She ...
- iOS使用NSTextAttachment添加图片,图片模糊
最近在忙的项目中,需要处理富文本的相关内容,产品需求并不复杂,所以想着用TextKit处理,顺便学习一下,没想到直接掉坑.在此记录一下(都是血泪史),顺便为有需要的小伙伴提供参考. // Add th ...
- Git命令diff格式详解
diff是Unix系统的一个很重要的工具程序. 它用来比较两个文本文件的差异,是代码版本管理的基石之一.你在命令行下,输入: $ diff <变动前的文件> <变动后的文件> ...
- C语言从1打印到100再打印到1该如何编写?我只服最后一种写法!
我觉得这是一个送分题,奈何人才太多了,给出了各种古怪的写法,如果是做项目的话,我比骄建议一些正常的写法,就是大家都能看得懂的,不要搞什么花里胡哨,不过你要是交流的话,既然是交流,我不觉得要多正规,即使 ...
- Privileged Permission开机授权时序图 SourceCode android-10.0.0_r36
Privileged Permission开机授权时序图 | SourceCode:android-10.0.0_r36 | Author:秋城 | v1.1SystemServerSystemSer ...
- CentOS8平台php日志的定时切分
一,编写bash脚本: [root@yjweb crontab]# vi split_php_logs.sh 代码: #!/bin/bash # 备份php/php-fpm的日志 # 昨天的日期 fi ...
- centos 7.8 添加磁盘后查看、分区、格式化、挂载
基础环境 公有云 由于磁盘空间快用完了,现在决定多加一个40G磁盘 第一步 分区 fdisk -l #查看当前磁盘信息 fdisk /dev/vdb #对指定磁盘进行操作 如上图一般磁盘的第一个分区都 ...