POJ 3126 Prime Path 解题报告(BFS & 双向BFS)
题目大意:给定一个4位素数,一个目标4位素数。每次变换一位,保证变换后依然是素数,求变换到目标素数的最小步数。
解题报告:直接用最短路。
枚举1000-10000所有素数,如果素数A交换一位可以得到素数B,则在AB间加入一条长度为1的双向边。
则题中所求的便是从起点到终点的最短路。使用Dijkstra或SPFA皆可。
当然,纯粹的BFS也是可以的。
用Dijkstra算法A了题目之后,看了一下Discuss,发现了一个新名词,双向BFS。
即从起点和终点同时进行BFS,相遇则求得最短路。
借鉴了思想,自己动手实现了代码。原本以为双向比单向快一倍而已,其实远远不止。
笔者用30W数据分别测试了单向和双向。环境为CodeBlock+MinGW4.7,Debug,双向时间为8.618s,而单向为惊人的139.989s!
简单思考了一下,也还是合理的。单向每次的增长是指数级的,而双向的指数只有单向的一半,优化程度相当高。
好了,贴代码~首先是双向BFS的Dijkstra:
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std; const int maxn=;
int prime[maxn];
const int maxV=;
int first[maxV],vv[maxV*maxV],nxt[maxV*maxV];
int num[maxV];
bool vis[][maxV];
int index; bool check(int a,int b)
{
int k=a-b;
if(k%==)
return true;
if(k< && k%== && a/==b/)
return true;
if(k< && k%== && a/==b/)
return true;
if(a/==b/)
return true;
return false;
} void calPrime()
{
for(int i=;i<maxn;i++) if(!prime[i])
{
for(int j=*i;j<maxn;j+=i)
prime[j]=true;
if(i>= && i<)
{
num[++index]=i;
prime[i]=index;
}
} int e=;
memset(first,,sizeof(first));
for(int i=;i<=index;i++)
for(int j=i+;j<=index;j++) if(check(num[j],num[i]))
{
nxt[e]=first[i],vv[e]=j,first[i]=e++;
nxt[e]=first[j],vv[e]=i,first[j]=e++;
}
} struct Node
{
int node;
int level;
bool operator<(const Node& cmp) const
{
return level>cmp.level;
}
} p,q; int Dijkstra(int sta,int end)
{
if(sta==end)
return ; memset(vis,,sizeof(vis)); sta=prime[sta];
end=prime[end]; priority_queue<Node> pq[];
p.node=sta;
p.level=;
vis[][p.node]=true;
pq[].push(p); p.node=end;
p.level=;
vis[][p.node]=true;
pq[].push(p); for(int i=; !pq[].empty() && !pq[].empty() ;i++)
{
int sel=;
if(pq[].size()>pq[].size())
sel++;
int level=pq[sel].top().level;
while(!pq[sel].empty())
{
p=pq[sel].top();
if(p.level!=level) //先判断,否则会pop掉丢失情况
break;
pq[sel].pop(); for(int e=first[p.node];e;e=nxt[e])
{
if(vis[-sel][vv[e]])
return i+;
if(!vis[sel][vv[e]])
{
q.level=p.level+;
q.node=vv[e];
vis[sel][vv[e]]=true;
pq[sel].push(q);
}
}
}
} return -;
} int main()
{
calPrime(); int T;
scanf("%d",&T);
while(T--)
{
int sta,end;
scanf("%d%d",&sta,&end);
int ans=Dijkstra(sta,end);
if(ans==-)
printf("Impossible\n");
else
printf("%d\n",ans);
}
}
然后是单向的BFS+Dijkstra:
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std; const int maxn=;
int prime[maxn];
const int maxV=;
int first[maxV],vv[maxV*maxV],nxt[maxV*maxV];
int num[maxV];
bool vis[maxV];
int index;
int count; bool check(int a,int b)
{
int k=a-b;
if(k%==)
return true;
if(k< && k%== && a/==b/)
return true;
if(k< && k%== && a/==b/)
return true;
if(a/==b/)
return true;
return false;
} void calPrime()
{
for(int i=;i<maxn;i++) if(!prime[i])
{
for(int j=*i;j<maxn;j+=i)
prime[j]=true;
if(i>= && i<)
{
num[++index]=i;
prime[i]=index;
}
} int e=;
memset(first,,sizeof(first));
for(int i=;i<=index;i++)
for(int j=i+;j<=index;j++) if(check(num[j],num[i]))
{
nxt[e]=first[i],vv[e]=j,first[i]=e++;
nxt[e]=first[j],vv[e]=i,first[j]=e++;
}
} struct Node
{
int k;
int w;
bool operator<(const Node& cmp) const
{
return w>cmp.w;
}
} p,q; int Dijkstra(int sta,int end)
{
memset(vis,,sizeof(vis));
end=prime[end]; p.k=prime[sta];
p.w=;
vis[p.k]=true; priority_queue<Node> pq;
pq.push(p); while(!pq.empty())
{
p=pq.top();
pq.pop(); if(p.k==end)
return p.w; for(int e=first[p.k];e;e=nxt[e]) if(!vis[vv[e]])
{
q.k=vv[e];
q.w=p.w+;
vis[q.k]=true;
pq.push(q);
}
}
return -;
} int main()
{
calPrime(); int T;
scanf("%d",&T);
while(T--)
{
int sta,end;
scanf("%d%d",&sta,&end);
int ans=Dijkstra(sta,end);
if(ans==-)
printf("Impossible\n");
else
printf("%d\n",ans);
}
}
测试数据我放在了百度云,有兴趣可以下载下来试一下:http://pan.baidu.com/share/link?shareid=4217669741&uk=2804348991
POJ 3126 Prime Path 解题报告(BFS & 双向BFS)的更多相关文章
- 双向广搜 POJ 3126 Prime Path
POJ 3126 Prime Path Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16204 Accepted ...
- BFS POJ 3126 Prime Path
题目传送门 /* 题意:从一个数到另外一个数,每次改变一个数字,且每次是素数 BFS:先预处理1000到9999的素数,简单BFS一下.我没输出Impossible都AC,数据有点弱 */ /**** ...
- POJ 3126 Prime Path(素数路径)
POJ 3126 Prime Path(素数路径) Time Limit: 1000MS Memory Limit: 65536K Description - 题目描述 The minister ...
- poj 3126 Prime Path bfs
题目链接:http://poj.org/problem?id=3126 Prime Path Time Limit: 1000MS Memory Limit: 65536K Total Submi ...
- POJ - 3126 - Prime Path(BFS)
Prime Path POJ - 3126 题意: 给出两个四位素数 a , b.然后从a开始,每次可以改变四位中的一位数字,变成 c,c 可以接着变,直到变成b为止.要求 c 必须是素数.求变换次数 ...
- POJ 3126 Prime Path 素数筛,bfs
题目: http://poj.org/problem?id=3126 困得不行了,没想到敲完一遍直接就A了,16ms,debug环节都没进行.人品啊. #include <stdio.h> ...
- POJ 3126 Prime Path(BFS 数字处理)
意甲冠军 给你两个4位质数a, b 每次你可以改变a个位数,但仍然需要素数的变化 乞讨a有多少次的能力,至少修改成b 基础的bfs 注意数的处理即可了 出队一个数 然后入队全部能够由这个素 ...
- (简单) POJ 3126 Prime Path,BFS。
Description The ministers of the cabinet were quite upset by the message from the Chief of Security ...
- POJ 3126 Prime Path【从一个素数变为另一个素数的最少步数/BFS】
Prime Path Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 26475 Accepted: 14555 Descript ...
随机推荐
- 2016.7.2this的应用
this有三个应用: 1.就是在类的方法中参数与成员参数重名了,那么用this.参数名=参数名来区分它们: 2.当一个引用对象要调用另一个已经有具体实例的引用对象,那么通过在类的定义中后面加publi ...
- [PR & ML 3] [Introduction] Probability Theory
虽然学过Machine Learning和Probability今天看着一part的时候还是感觉挺有趣,听惊呆的,尤其是Bayesian Approach.奇怪发中文的笔记就很多人看,英文就没有了,其 ...
- Demo02_对结构体进行文件读写_张仕传_作业_
#include <iostream> using namespace std; #define StructArrarySize 5 // 老师数量 #define StudentNum ...
- 省市选择(基于zepto.js)
效果如下: <div class="clList overflow-h mt75"> <select class="pull-left cl-35 se ...
- JSONP(跨域请求) —— 一种非官方跨域数据交互协议
1.JSONP的作用 由于同源策略的限制,XmlHttpRequest只允许请求当前源(域名.协议.端口)的资源,为 了实现跨域请求,可以通过script标签实现跨域请求,然后再服务器端输出JSON数 ...
- 为什么a标签中使用img后的高度多了几个像素?
a元素下有一个匿名文本,这个文本外有一个匿名行级盒子,它有的默认vertical-align是baseline的,而且往往因为上文line-height的影响,使它有个line-height,从而使其 ...
- 最完美解决Nginx部署ThinkPHP项目的办法
网上通用解决方法的配置如下: server { ... location / { index index.htm index.html index.php; #访问路径的文件不存在则重写URL转交给T ...
- oracle LogMiner配置使用
一.安装LogMiner1.@D:\app\product\11.1.0\db_1\RDBMS\ADMIN\dbmslm.sql 2.@D:\app\product\11.1.0\db_1\RDBMS ...
- TNS-12541: TNS:no listener TNS-12560: TNS:protocol adapter error
新建的数据库,在配置完listener的时候报这个错. 参考文章:https://community.oracle.com/message/4098938 http://blog.csdn.net/l ...
- HBase的安装与使用
1.安装 由于还是学习阶段,所以没有在生产环境练习,就在本地建了个虚拟机进行HBase的安装. 下载地址http://www.apache.org/dyn/closer.cgi/hbase/,选择一个 ...