poj3126
题意:
给出两个4位数的素数A
和B
。从A
开始,要求改变1位数字,使得新的四位数仍是素数,问最少改变多少次可以变成B
?不存在则输出Impossible
题解:
首先看到这题要用的肯定有素数筛了
筛出1000~9999的素数放在数组p
里
接着就是要把数转化成图的问题(毕竟图容易求得最少步数)
假设有2个数a
和b
,若他们是‘相邻’(只相差1个数字)的,用邻接表添加a到b和b到a的两条边。假设所有素数的‘相邻’关系已经建立完成了,那么在图里从A
出发,每次向外走一步,用vis记录走过的结点,只要到达了B
就停止搜索。
现在还剩一个判断‘相邻’的问题,很简单。
对a
和b
依次取出每一位,两两比较,只要有3次及以上相同即为相邻。
第一次写的时候只简单的以为考虑b-a
就行了,只要是整千、整百、整十或十以下就相邻,但有几个反例,例如8089
和8179
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn=1e4;
int T,a,b,ans,vis[maxn];
int prime[maxn],p[maxn];
vector<int> edge[maxn];
struct node
{
int val,step;
node(int v,int s)
{
val=v;step=s;
}
};
void getprime()
{
for(int i=2;i<maxn;i++)
{
if(!prime[i])
{
prime[++prime[0]]=i;
if(i>=1000)
p[++p[0]]=i;
}
for(int j=1;j<=prime[0] && i*prime[j]<maxn;j++)
{
prime[i*prime[j]]=1;
if(i%prime[j]==0)
break;
}
}
}
bool judge(int x,int y)
{
int cnt=0;
while(x)
{
if(x%10==y%10)
cnt++;
x/=10;
y/=10;
}
if(cnt>=3)
return true;
else return false;
}
void build()
{
for(int i=1;i<=p[0];i++)
{
for(int j=i+1;j<=p[0];j++)
{
if(judge(p[i],p[j]))
{
edge[p[i]].push_back(p[j]);
edge[p[j]].push_back(p[i]);
}
}
}
}
void bfs()
{
queue<node> q;
while(!q.empty()) q.pop();
q.push(node(a,0));
vis[a]=1;
while(!q.empty())
{
node temp=q.front();
q.pop();
if(temp.val==b)
{
ans=temp.step;
return;
}
for(int i=0;i<edge[temp.val].size();i++)
{
int v=edge[temp.val][i];
if(!vis[v])
{
vis[v]=1;
q.push(node(v,temp.step+1));
}
}
}
}
int main()
{
getprime();
//printf("%d\n",p[0]);
build();
scanf("%d",&T);
while(T--)
{
ans=-1;
memset(vis,0,sizeof(vis));
scanf("%d %d",&a,&b);
bfs();
if(ans==-1)
printf("Impossible\n");
else printf("%d\n",ans);
}
return 0;
}
poj3087
题意:
有2个栈S1
和S2
,2个栈合并的时候先取出S1
的栈顶再取出S2
的栈顶交叉排列。差不多就是(S1 S2 S1 S2…S1 S2)。新合并的栈S12
要拆分的话是将上半部分作为S2
,下半部分作为S1
,然后又可以进行合并。。。。
给出S1
,S2
和S12
,问S1
S2
最少合并几次可以变成S12
?不存在则输出-1
题解:
这跟搜索有关系嘛???
直接模拟不就行了,用map记录出现过的S12
,若重复出现了则不存在。
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=1e4;
int T;
int n;
string s1,s2,sn,temp;
map<string,int> vis;
int ans;
int main()
{
cin>>T;
for(int k=1;k<=T;k++)
{
vis.clear();
ans=0;
cin>>n;
cin>>s1>>s2>>sn;
while(1)
{
temp.clear();
for(int i=0;i<n;i++)
{
temp.push_back(s2[i]);
temp.push_back(s1[i]);
}
ans++;
//cout<<temp<<endl;
if(temp==sn)
break;
if(!vis[temp])
{
vis[temp]=1;
s1.clear();
s2.clear();
for(int i=0;i<n;i++)
s1.push_back(temp[i]);
for(int i=n;i<2*n;i++)
s2.push_back(temp[i]);
}
else
{
ans=-1;
break;
}
}
printf("%d %d\n",k,ans);
}
return 0;
}