zoukankan      html  css  js  c++  java
  • 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
    ");
            else printf("%d
    ",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
    ",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)
    ");break;
            case 2:
                printf("FILL(2)
    ");break;
            case 3:
                printf("DROP(1)
    ");break;
            case 4:
                printf("DROP(2)
    ");break;
            case 5:
                printf("POUR(1,2)
    ");break;
            case 6:
                printf("POUR(2,1)
    ");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
    ");
        return 0;
    }





  • 相关阅读:
    用汇编的眼光看C++(之算术符重载) 四
    用汇编的眼光看C++(之嵌入汇编) 四
    用汇编的眼光看C++(之const属性) 四
    用汇编的眼光看C++(之虚函数) 四
    用汇编的眼光看C++(之类继承) 四
    用汇编的眼光看C++(之模板类) 四
    用汇编的眼光看C++(之class构造、析构) 四
    用汇编的眼光看C++(之类静态变量、静态函数) 四
    用汇编的眼光看C++(之特殊函数) 四
    多线程基础知识
  • 原文地址:https://www.cnblogs.com/01world/p/5762841.html
Copyright © 2011-2022 走看看