poj 几道简单的搜索题(二)

题目:poj 3278

题意:

在[0,100000]上,给定两个整数n和k通过 n+1或n-1 或n*2 这3种操作,使得n==k,输出最少的操作次数
分析:
bfs入门题,每个状态记录一下位置和步数,然后bfs就好。


题目:poj 1426

题意:

给一个正整数n,找出n的某个倍数m,m可以用01表示。n<=200,m不超过100位

分析:

看完m的数据范围吓傻了QAQ,可是n才200,然后写了个暴力打表,发现没有超过18位的!

这题的正规解法是bfs。

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
typedef unsigned long long ull;
ull bfs(ull n)
{
    queue<ull>q;
    q.push(1);
    while(!q.empty()){
        ull t=q.front();q.pop();
        if(t%n==0)return t;
        q.push(t*10);
        q.push(t*10+1);
    }
    return 0;//题目说一定有解,不加居然WA!
}
int main()
{
    ull n;
    while(cin>>n&&n){
        cout<<bfs(n)<<endl;
    }
    return 0;
}

题目:poj 3126

题意:

给两个四位的素数s和e,每次可以改变一位数字(只能是四位素数),问从s到e的最短路?

分析:

先打个素数表,来判断四位数是否为素数。然后简单的bfs。每次可以改变1位数,那么就一次改变第一位,第二位,第三位,第四位,然后判断是否入队。

有点麻烦的地方是类型转换。

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
#define mp make_pair
const int N=10000;
typedef pair<int,int>pii;
bool prime[N],vis[N];
int s,e;
void getPrime()
{
    memset(prime,0,sizeof(prime)); //prime[i]==0是素数
    int m=sqrt(N+0.5);
    for(int i=2;i<=m;i++)if(!prime[i])
        for(int j=i*i;j<N;j+=i)prime[j]=1;

}
int bfs()
{
    memset(vis,0,sizeof(vis));
    stringstream ss;
    string s1,s2;
    int x1,x2;
    queue<pii>q;
    q.push(mp(0,s));
    vis[s]=1;
    while(!q.empty()){
        pii t=q.front();q.pop();
        int step=t.first, x=t.second;
        if(x==e)return step;
        ss.clear(); //要注意clear
        ss<<x;ss>>s1;s2=s1;
        for(char i='1';i<='9';i++){
            ss.clear();
            s2[0]=i;ss<<s2;ss>>x1;
            if(!vis[x1]&&!prime[x1])q.push(mp(step+1,x1));
            vis[x1]=1;
        }
        s2=s1;
        for(char i='0';i<='9';i++){
            ss.clear();
            s2[1]=i;ss<<s2;ss>>x1;
            if(!vis[x1]&&!prime[x1])q.push(mp(step+1,x1));
            vis[x1]=1;
        }
        s2=s1;
        for(char i='0';i<='9';i++){
            ss.clear();
            s2[2]=i;ss<<s2;ss>>x1;
            if(!vis[x1]&&!prime[x1])q.push(mp(step+1,x1));
            vis[x1]=1;
        }
        s2=s1;
        for(char i='0';i<='9';i++){
            ss.clear();
            s2[3]=i;ss<<s2;ss>>x1;
            if(!vis[x1]&&!prime[x1])q.push(mp(step+1,x1));
            vis[x1]=1;
        }
    }
    return -1;
}
int main()
{
    getPrime();
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&s,&e);
        int t=bfs();
        if(t==-1)printf("Impossible\n");
        else printf("%d\n",t);
    }
    return 0;
}

题目:poj 3414

题意:

给出两个杯子的容量A,B,然后给出六种倒水方式:

1.把A灌满

2.把B灌满

3.把A清空

4.把B清空

5.把A中的水倒入B中,有可以倒满的话,A可剩余一些水,不能倒满,A空

6.把B中的贺岁倒入A中,与5相似

通过以上六种方式(实际上是八种),问是否可以得到一杯体积是C的水?

分析:

简单的bfs最短路问题,只不过打印方案比较麻烦。

可以设一个pre,记录一下前一个状态,一个id,记录得到当前状态的操作。这样bfs可以得到最优解后,往前找pre即可。

#include<cstring>
#include<cstdio>
#include<stack>
using namespace std;
const int N=111;
bool vis[N][N];
int A,B,C;
struct state
{
    int x,y,step,pre,id;
}q[N*N];
void print(state over)
{
    printf("%d\n",over.step);
    stack<int>ans;
    while(over.step){ //往前找,把最短路保存到栈里,然后一个个打印
        ans.push(over.id);
        over=q[over.pre];
    }
    while(!ans.empty()){
        int t=ans.top();ans.pop();
        switch(t)
        {
        case 1:
            printf("FILL(1)\n");break;
        case 2:
            printf("FILL(2)\n");break;
        case 3:
            printf("DROP(1)\n");break;
        case 4:
            printf("DROP(2)\n");break;
        case 5:
            printf("POUR(1,2)\n");break;
        case 6:
            printf("POUR(2,1)\n");break;
        }
    }
}
bool bfs()
{
    memset(vis,0,sizeof(vis));
    int head=0,tail=0;
    q[tail++]=((state){0,0,0,-1,-1});
    while(head<tail){
        state t=q[head];
        int a=t.x,b=t.y,step=t.step;
        if(a==C||b==C){
            print(t);
            return true;
        }
        if(!vis[A][b]){ //FILL(1)
            vis[A][b]=1;
            q[tail++]=((state){A,b,step+1,head,1});
        }
        if(!vis[a][B]){ //FILL(2)
            vis[a][B]=1;
            q[tail++]=((state){a,B,step+1,head,2});
        }
        if(!vis[0][b]){ //DROP(1)
            vis[0][b]=1;
            q[tail++]=(state){0,b,step+1,head,3};
        }
        if(!vis[a][0]){ //DROP(2)
            vis[a][0]=1;
            q[tail++]=(state){a,0,step+1,head,4};
        }
        if(b+a>B&&!vis[a-(B-b)][B]){ //POUR(1,2),1杯有剩余
            vis[a-B+b][B]=1;
            q[tail++]=(state){a-B+b,B,step+1,head,5};
        }
        if(b+a<=B&&!vis[0][a+b]){ //POUR(1,2) ,1杯子无剩余
            vis[0][a+b]=1;
            q[tail++]=(state){0,a+b,step+1,head,5};
        }
        if(b+a>A&&!vis[A][b-(A-a)]){ //POUR(2,1),2杯子有剩余
            vis[A][b-A+a]=1;
            q[tail++]=(state){A,b-A+a,step+1,head,6};
        }
        if(b+a<=A&&!vis[a+b][0]){ //POUR(2,1),2杯子无剩余
            vis[a+b][0]=1;
            q[tail++]=(state){a+b,0,step+1,head,6};
        }
        head++;
    }
    return false;
}

int main()
{
    scanf("%d%d%d",&A,&B,&C);
    if(!bfs())printf("impossible\n");
    return 0;
}





转载于:https://www.cnblogs.com/01world/p/5762841.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值