POJ 2432
\(\mathbf{POJ\;2432}\)题解
题意
给出圆上的\(N\)个点,每个点有一个经度(大于\(0\)小于\(360\));再给出\(M\)条双向边,保证边\(x y\)仅会沿圆上较短的弧连接,且不存在边连接圆上相对的两个点的情况。
求一条从点\(1\)出发最后回到点\(1\),且能环绕圆的经过点数最少的路径。
思路
边权为\(1\)的最短路,显然可以想到BFS。但由于还要满足“能环绕圆”这一条件,我们需要加一些限制。
不妨预处理出每条边的连接的两地间的经度差作为边权,顺时针边置正权,逆时针边置负权,并在BFS的状态中加入一维,表示路径权值和。
那么在BFS时,就可以用已走过的路径权值和\(dis\)来判断一条从\(1\)出发再回到\(1\)的路径是否合法了。
不难发现,若\(dis\)不为\(0\),那么一条从\(1\)出发回到\(1\)的路径一定是合法的,反之亦然。
另外,一个状态\(f(x,dis)\)一定不会出现两次,所以用一个集合(STL set)来记录已经出现过的状态,起一般BFS中标记数组的作用。
最后,在计算答案时用一个成员变量\(step\)记录经过了几个点。
使用以上算法即可通过本题。如果想进一步优化,可以把queue改为手写queue,set改为手写Hash。
代码
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
//include STL queue
#include<queue>
//include STL set
#include<set>
//include STL pair
#include<utility>
#define N 5005
#define M 25005
using namespace std;
struct pos{
int x,dis;
int step;
}tmp,fro;
struct Edge{
int nxt,to,w;
}e[M<<1];
int n,m,tot=1,head[N],a[N];
queue<pos>q;
set<pair<int,int> >cnt;
void addedge(int x,int y,int z)
{
e[++tot]=(Edge){head[x],y,z},head[x]=tot;//顺时针
e[++tot]=(Edge){head[y],x,-z},head[y]=tot;//逆时针
}
int getdis(int x,int y)//返回两地经度差
{
int z=min(abs(x-y),360-abs(x-y));
if((x+z)%360==y)
return z;//顺时针
else
return -z;//逆时针
}
int bfs()
{
fro.x=1;fro.dis=0,fro.step=0;
q.push(fro);
while(!q.empty())
{
fro=q.front(),q.pop();
int x=fro.x,dis=fro.dis,step=fro.step;
cnt.insert(make_pair(x,dis));
for(int i=head[x],y;i;i=e[i].nxt)
{
y=e[i].to;
if(y==1 && dis+e[i].w)
return step+1;
if(cnt.find(make_pair(y,dis+e[i].w))!=cnt.end())
continue;
tmp.x=y,tmp.dis=dis+e[i].w,tmp.step=step+1;
q.push(tmp);
}
}
return -1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
for(int i=1,x,y,z;i<=m;i++){
scanf("%d%d",&x,&y);
z=getdis(a[x],a[y]);
if(z>0) addedge(x,y,z);//顺时针
else addedge(y,x,-z);//逆时针
}
printf("%d\n",bfs());
return 0;
}
/*
3 3
0
120
240
1 2
2 3
1 3
*/
完结撒花
POJ 2432的更多相关文章
- poj 2432 Around the world bfs+哈希
由于每个点的状态包含走过来的距离,所以要存二维的状态,但是状态总量太多,所以可以用哈希来搞. 那么就是bfs最短路,哈希记录状态了. #include <iostream> #includ ...
- poj和hdu部分基础算法分类及难度排序
最近想从头开始刷点基础些的题,正好有个网站有关于各大oj的题目分类(http://www.pythontip.com/acm/problemCategory),所以写了点脚本把hdu和poj的一些题目 ...
- POJ 3370. Halloween treats 抽屉原理 / 鸽巢原理
Halloween treats Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7644 Accepted: 2798 ...
- POJ 2356. Find a multiple 抽屉原理 / 鸽巢原理
Find a multiple Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7192 Accepted: 3138 ...
- POJ 2965. The Pilots Brothers' refrigerator 枚举or爆搜or分治
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22286 ...
- POJ 1753. Flip Game 枚举or爆搜+位压缩,或者高斯消元法
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 37427 Accepted: 16288 Descr ...
- POJ 3254. Corn Fields 状态压缩DP (入门级)
Corn Fields Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 9806 Accepted: 5185 Descr ...
- POJ 2739. Sum of Consecutive Prime Numbers
Sum of Consecutive Prime Numbers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 20050 ...
- POJ 2255. Tree Recovery
Tree Recovery Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11939 Accepted: 7493 De ...
随机推荐
- Centos-实时监控系统处理器状态-top
top 实时监控处理器状态的实时监控,能够显示系统中各个进程的资源占用状况 相关选项 -d 指定每两次屏幕信息刷新之间间隔秒数 -i 不显示闲置或者僵死进程信息 -c 显示进程整个命令路径 -s 安 ...
- Python-为元组中每个元素命名
学生信息系统: (名字,年龄,性别,邮箱地址) 为了减少存储开支,每个学生的信息都以一个元组形式存放 如: ('tom', 18,'male','tom@qq.com' ) ('jom', 18,'m ...
- CentOS7设置内网时间同步
1.yum 安装 NTP服务器 [root@master ~]# yum -y install ntp 2.启动ntpd服务 [root@master ~]# systemctl start ntpd ...
- P3378 堆(模板)
P3378 [模板]堆 题目描述 给定一个数列,初始为空,请支持下面三种操作: 给定一个整数 x,请将 x 加入到数列中. 输出数列中最小的数. 删除数列中最小的数(如果有多个数最小,只删除 1 个) ...
- 制作u盘启动盘
制作u盘启动盘 如果是想要制作 windows 系统启动盘,windows 官网提供途径,这里不在赘述. 以下讨论制作 centos 系统启动盘,需要 centos 系统文件,开源,可从官网下载得到. ...
- 树形DP 学习笔记
树形DP学习笔记 ps: 本文内容与蓝书一致 树的重心 概念: 一颗树中的一个节点其最大子树的节点树最小 解法:对与每个节点求他儿子的\(size\) ,上方子树的节点个数为\(n-size_u\) ...
- 实验 5:OpenFlow 协议分析和 OpenDaylight 安装
一.实验目的 回顾 JDK 安装配置,了解 OpenDaylight 控制的安装,以及 Mininet 如何连接;通过抓包获取 OpenFlow 协议,验证 OpenFlow 协议和版本,了解协议内容 ...
- windows.h系统函数
转载:https://blog.csdn.net/u010756046/article/details/82432312 // Windows系统函数.cpp: 定义控制台应用程序的入口点.// #i ...
- 初学者的Android移植:在Debian上建立一个稳定的构建环境
介绍 通过在chrooted环境中设置开发环境,避免依赖冲突和沙箱您的Android开发从您的Debian GNU/Linux系统.这是为通配符类别准备的,因为从源代码构建Android似乎没有在其他 ...
- MeteoInfoLab脚本示例:添加南海脚图
添加南海脚图实际上就是增加一个地图坐标系(Axesm),在用axesm函数创建地图坐标系的时候可以指定position参数(即位置和大小),第1和第2个参数是坐标系的左下角x, y位置,后两个参数是坐 ...