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 ...
随机推荐
- 严重: Exception starting filter struts2
我是用了右键-Add Struts.. 所以,不应该在WebRoot->WEB-INF->lib中加入5个基本包了...
- 使用CHttpFile从服务器端正确的读取数据
前段时间在给软件做升级提示模块的时候发现一个问题,就是使用CHttpFile对象无法从服务器端获取到正确的响应数据长度,无论是使用CHttpFile:: QueryInfo方法,还是使用CHttpFi ...
- 【HeadFirst设计模式】8.模板方法模式
模板方法 定义: 在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使用得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 策略模式: 定义一个算法家族,并让这些算法可以互 ...
- Node.js:JavaScript脚本运行环境
Node.js https://nodejs.org/ 2016-08-03
- C# WinForm实现控件拖动实例介绍
主要是设计控件的MouseDown.MouseLeave.MouseMove事件.一步步来吧:1.定义一个枚举类型,描述光标状态 private enum EnumMousePointPosition ...
- 建站服务器的最优选择之Windows Or Linux
转载于:http://www.0553114.com/news/detail-702287.html 不管是个人建站,还是中小型企业建站,选择一款合适的主机是站长朋友们共同的心愿.主机是选择Windo ...
- Activity组件
Activity 间书作者:阿敏其人 关于Activity博文上 间书作者:阿敏其人 关于Activity博文中 间书作者:阿敏其人 关于Activity博文下
- Css3 阴影效果
box-shadow:#333 0 0 5px 10px; //上下左右有阴影-webkit-box-shadow: #666 0px 5px 10px; -moz-box-shadow: #666 ...
- codeforces edu round3
B. The Best Gift 传送门:http://codeforces.com/problemset/problem/609/B Emily's birthday is next week a ...
- 【JPA】表达条件查询的关键字
1.通过解析方法名创建查询 框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如 find.findBy.read.readBy.get.getBy,然后对剩下部分进行解析.并且如果方法的最后一 ...