UVA - 12101 解题报告

题目链接
题目大意,给你两个素数,一次只能改变一位,问多少次能改变完成,不能则输出impossible

这道题,一开始拿到手之后,并不知道怎么做,联想一下最短路径想到BFS,但是感觉BFS没有办法解决,便没有尝试,比赛完之后,看了别人的代码竟然真的是BFS,然后尝试着自己写了写,结果连样例都没过去,原因是没有及时进行位数的还原(代码中会有体现),一开始写的时候还忘了标记使用(傻得不谈了),最后来一句,BFS大法好。

下面给出AC代码:


#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 10000+10;
bool table[maxn],used[maxn];


void prime_table()
{
    memset(table,0,sizeof(table));

    int m=(int)sqrt(maxn+0.5);
    for(int i=2;i<=m;i++)
    {
        if(!table[i])
            for(int j=i*i;j<=maxn;j+=i)
               table[j]=true;
    }
}

struct node
{
    int rep;
    int step;
    node() {}
    node(int a,int b):rep(a),step(b) {}
};



int BFS(int str,int ed)
{
    memset(used,0,sizeof(used));
    queue<node> que;
    que.push(node(str,0));
    used[str]=true;//标记使用

    while(!que.empty())
    {
        node p=que.front(); que.pop();
        if(p.rep==ed) return p.step;

        int sut=p.rep,t[5];
        t[1]=sut/1000,t[2]=(sut/100)%10,t[3]=(sut/10)%10,t[4]=sut%10;
        for(int i=1;i<=4;i++)
        {
            int tmp=t[i];//注意位数改变完之后一定要及时还原,否则会影响后续的使用
            for(int j=0;j<=9;j++)
            {
                if(j==0&&i==1) continue;//没有前导0
                t[i]=j;
                int st=t[1]*1000+t[2]*100+t[3]*10+t[4];
                if(!table[st]&&!used[st])
                {
                    que.push(node(st,p.step+1));
                    used[st]=true;
                }
            }
            t[i]=tmp;//位数还原
        }

    }
    return -1;
}

int main()
{
    prime_table();
    int T; scanf("%d",&T);
    while(T--)
    {
       int str,ed; scanf("%d %d",&str,&ed);
       int cnt=BFS(str,ed);
       if(cnt!=-1) printf("%d\n",cnt);
       else printf("Impossible\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/NCC__dapeng/article/details/81914499