题目大意:给定一个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)的更多相关文章

  1. 双向广搜 POJ 3126 Prime Path

      POJ 3126  Prime Path Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16204   Accepted ...

  2. BFS POJ 3126 Prime Path

    题目传送门 /* 题意:从一个数到另外一个数,每次改变一个数字,且每次是素数 BFS:先预处理1000到9999的素数,简单BFS一下.我没输出Impossible都AC,数据有点弱 */ /**** ...

  3. POJ 3126 Prime Path(素数路径)

    POJ 3126 Prime Path(素数路径) Time Limit: 1000MS    Memory Limit: 65536K Description - 题目描述 The minister ...

  4. poj 3126 Prime Path bfs

    题目链接:http://poj.org/problem?id=3126 Prime Path Time Limit: 1000MS   Memory Limit: 65536K Total Submi ...

  5. POJ - 3126 - Prime Path(BFS)

    Prime Path POJ - 3126 题意: 给出两个四位素数 a , b.然后从a开始,每次可以改变四位中的一位数字,变成 c,c 可以接着变,直到变成b为止.要求 c 必须是素数.求变换次数 ...

  6. POJ 3126 Prime Path 素数筛,bfs

    题目: http://poj.org/problem?id=3126 困得不行了,没想到敲完一遍直接就A了,16ms,debug环节都没进行.人品啊. #include <stdio.h> ...

  7. POJ 3126 Prime Path(BFS 数字处理)

    意甲冠军  给你两个4位质数a, b  每次你可以改变a个位数,但仍然需要素数的变化  乞讨a有多少次的能力,至少修改成b 基础的bfs  注意数的处理即可了  出队一个数  然后入队全部能够由这个素 ...

  8. (简单) POJ 3126 Prime Path,BFS。

    Description The ministers of the cabinet were quite upset by the message from the Chief of Security ...

  9. POJ 3126 Prime Path【从一个素数变为另一个素数的最少步数/BFS】

    Prime Path Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 26475 Accepted: 14555 Descript ...

随机推荐

  1. HDOJ 1024 Max Sum Plus Plus -- 动态规划

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1024 Problem Description Now I think you have got an ...

  2. HTML5 Video与Audio 视频与音频

    ---- 视频Video对象 - 指定视频播放地址 <video width="320" height="240" controls="cont ...

  3. ECMAScript布尔操作符

    在ECMAScript中提供了Boolean()转换函数以及三个布尔操作符,这三个布尔操作符分别为逻辑非.逻辑与.逻辑或,这三个操作符通常用作于某些值的求反,比较模式等.学好这一点知识也非常的重要,奠 ...

  4. Web前端新人笔记之jquery入门

    本章将为大家介绍以下几点内容: 1.jquery的主要特点: 2.建立jquery的编码环境: 3.简单jquery脚本示例: 4.选择jquery而不是纯javaScript的理由: 5.常用的jq ...

  5. jquery ajax php 无刷新上传文件 带 遮罩 进度条 效果的哟

    在很多项目中都会叫用户上传东西这些的,自从接触了jquery 和ajax之后就不管做什么,首先都会想到这个,我这个人呢?是比较重视客户体验的,这次我这边负责的是后台板块,然后就有一块是要求用户上传照片 ...

  6. centos 7.0 mono&Jexus V5.5.3安装

    首先我们需要先配置一下yum源中mono的引用说明: 第一步: vi /etc/yum.repos.d/mono.repo 第二步:在刚打开的文件中编辑如下内容 [mono]name=monobase ...

  7. JSON对象的stringify()和parse()方法

    1.stringify() ---- JavaScript对象序列化为JSON字符串 eg1. var book = {title: 'JS', authors: ['Van'], edition:3 ...

  8. Unity3D--学习太空射击游戏制作(四)

    步骤七:添加声音和特效(射击声音和爆炸效果) 01:在Project窗口单机右键,选择Import Package->Custome Package,然后到资源文件目录packages浏览uni ...

  9. php练习1——计算器

    目标:输入两个数,计算两个数的和/差/积/商 程序如下:两个文件jiSuanQi.html和jiSuanQi.php    结果如下:  

  10. mysql 远程连接 1045 Access denied for user 'root'@'XX.XX.XX.XX' (using password:YES)

    用户名/密码错误,需要输入开放远程时设置的密码