zoukankan      html  css  js  c++  java
  • $Luogu$ $P2243$ 电路维修

    链接

    背景

    杜宇飞,石家庄二中【 (Nescafé) (5) 】杯 (NOIP) 模拟赛, (Luogu) (P2243/CH2601)

    题意

    对于 (T) 组数据,每次给定一个 (r imes c) 的网格,分别为字符左右斜杠表示电路的方向。电流可以经过电路和格点流动。每个格子可以自由旋转任意次,每次只能旋转 (90^circ) 。求从左上角的格点到右下角的格点有电流经过的最小旋转次数。若电流不能到达输出 ( extrm{NO SOLUTION})

    解法

    显然每个格子只可能是不动或者旋转一次的,否则必然不优。
    考虑怎么建图。不妨考虑把所有的格点形成一个 ((r+1) imes (c+1)) 的点阵,分别从 (1)((r+1) imes (c+1)) 编号。这样就可以考虑对每个网格的对角线连边了。由于本身就存在电路的对角线不需要移动,所以建 (0) 边;若所在网格的电路与当前的对角线垂直,则沿着任意方向旋转一次就可以有电流流经,于是建 (1) 边。
    然后就是跑最短路了。
    堆优化 (dijkstra) 当然是可以过的,但是不够快。可以考虑线段树优化。这里不多讲了。
    如果你要用那个死了的算法的话,显然网格图能把你卡飞。
    由于边权只有 (1)(0) 两种,考虑 (0-1) (bfs) (双端队列 (bfs) )。做法是 (0) 边放进队首, (1) 边放进队尾。其他的细节和那个死了的算法没有啥区别。唯一的区别是不用判断能不能松弛,大力取 (min) 就是了。

    细节

    (1.)务必务必务必建无向边!!!

    (2.) 有字符串读入建议用 (cin) 。读进来立马建好边,注意从 (0) 开始标号。

    (3.) 记得初始化 (dis)(inf) ,后面还要判无解。

    (4.) 多组数据,该清空的都要清空。

    代码

    $View$ $Code$ ```cpp #include using namespace std; inline int read() { int ret=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { ret=(ret<<1)+(ret<<3)+ch-'0'; ch=getchar(); } return ret*f; } const int inf=0x3f3f3f3f; int T,r,c,dis[300005]; int num,head[300005]; char s[505]; bool vis[300005]; deque q; struct edge { int ver,nxt,w; }e[2000005]; inline void adde(int u,int v,int w) { e[++num].ver=v; e[num].nxt=head[u]; e[num].w=w; head[u]=num; } inline void bfs(int s) { q.clear(); dis[s]=0; q.push_front(s); while(!q.empty()) { int x=q.front(); q.pop_front(); if(vis[x]) continue; vis[x]=1; for(register int i=head[x];i;i=e[i].nxt) { int y=e[i].ver; if(e[i].w) { dis[y]=min(dis[y],dis[x]+1); q.push_back(y); } else { dis[y]=min(dis[y],dis[x]); q.push_front(y); } } } } int main() { T=read(); while(T--) { r=read(); c=read(); num=0; memset(head,0,sizeof(head)); for(register int i=1;i<=r;i++) { scanf("%s",s); for(register int j=1;j<=c;j++) { int leftup=(i-1)*(c+1)+j,leftdown=i*(c+1)+j,rightup=(i-1)*(c+1)+j+1,rightdown=i*(c+1)+j+1; if(s[j-1]=='\') { adde(leftup,rightdown,0); adde(rightdown,leftup,0); adde(leftdown,rightup,1); adde(rightup,leftdown,1); } else { adde(leftup,rightdown,1); adde(rightdown,leftup,1); adde(leftdown,rightup,0); adde(rightup,leftdown,0); } } } memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); bfs(1); if(dis[(r+1)*(c+1)]
  • 相关阅读:
    愚公oracle数据库同步工具
    外部服务的隔离及降级
    使用redis来实现分布式锁
    php 无限极栏目 Tree 树格式 层级显示 【列表记录按顺序缩进显示】
    腾讯地图添加多marker标注样式
    MIME 视频 , 文件下载与播放权限
    php json_encode 对浮点 精度 问题 解决
    phpexcel 导入 时间格式 和 数值格式 处理
    phpexcel写入追加已有的excel文件
    php 判断字符串是否可以转 浮点型
  • 原文地址:https://www.cnblogs.com/Peter0701/p/11847216.html
Copyright © 2011-2022 走看看