王道机试指南 P4 (搜索)

1.题目一:
在这里插入图片描述

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<queue>
#include<stack>
using namespace std;
//白鸡问题,小于等于n元去买100只鸡,大鸡5元,小鸡 3元,还有1/3元的鸡 求x,y,z 并且以x增大为序列
//想法一 处理这个排序问题的话,就需要用一个结构体数组,把x,y,z存入?然后再排序输出,然后使用一次暴力,然后三次循环
struct M{
    int x,y,z;
}Num[100];
bool cmp(M a,M b){
    //先比较x,再x相同情况下,比较Y,最后是x
    if(a.x!=b.x)
        return a.x<b.x;
    else if(a.y!=b.y)
        return a.y<b.y;
    else
       return  a.z<b.z;
}
int main()
{
    int i,j,k,t=0;
    int n;
    while(scanf("%d",&n)!=EOF){
    for(i=0;i<100;i++)//其实这些对于循环的条件都是可以再改进一下的,也可以不用
    for(j=0;j<100;j++)
    for(k=0;k<100;k++){
        if(i+j+k==100&&(3*5*i+3*3*j+1*k)<=3*n){//其实这里主要是把三分之一给化解掉
            //在满足这些的条件之下
            Num[t].x=i;
            Num[t].y=j;
            Num[t].z=k;
            t++;
        }

    }
    //对这个结构体数组进行排序
    sort(Num,Num+t,cmp);
    //再进行输出
    for(i=0;i<t;i++)
        printf("x=%d,y=%d,z=%d\n",Num[i].x,Num[i].y,Num[i].z);
    }

}

问题二:BFS
这道题本身是不难的,套用bfs模板就行。可是就是因为自己的一点点小疏忽,把一个x错写成了y,导致找了半天的BUg,苦恼苦恼。。。(大伙们一定要仔细啊!!)
在这里插入图片描述

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<queue>
#include<stack>
using namespace std;
//对于BFS来说,需要有队列的参与,每次都是进队,同理这道题的bfs的参数是三个坐标,但是会在队列中多一个时间的坐标,用来表示现在走了多久
//每次进队列的时候,都是之前那个队列出来的时间加一
//然后当然还需要一个三维数组来存xyz,和一个数组来判断有没有被访问过
int map[50][50][50];
bool make[50][50][50];//一个是用以输入,一个是用以判断
int a,b,c,t;//表示的就是坐标位置
//然后创建一个结构体用来存数据
struct M{
    int x,y,z,t;//分别代表三个坐标和时间
};
bool judge(int x,int y,int z){
    //写一个判断是否可以选这个位置的函数
    //把越界单独写出来吧
    if(x<0||x>=a||y<0||y>=b||z<0||z>=c)
        return false;
    if(map[x][y][z]==0&&make[x][y][z]==false)
        return true;//如果这个地方是路,并且没有被访问过
    return false;
}
//还要写三个数组用来(其实直接用一个二维数组就行)
int stepx[6]={0,0,0,0,1,-1};
int stepy[6]={0,0,1,-1,0,0};
int stepz[6]={1,-1,0,0,0,0};
int BFS(int x,int y,int z,int t){
    //这里返回值是int 因为需要返回对应的时间
    //首先让他进队吧,可是这个时间怎么算呢,那我的想法就是这里再加一个时间
    //先创建一个队列
    queue<M> q;
    M temp;
    temp.x=x;
    temp.y=y;
    temp.z=z;
    temp.t=t;
    //然后让这个temp进队列
    q.push(temp);
    while(!q.empty()){
        //在他非空的情况之下,然后删去队头
        temp=q.front();//取出对头元素
        //这里可以有一个判断
        if(temp.x==a-1&&temp.y==b-1&&temp.z==c-1)
            return temp.t;
        q.pop();
       // printf("%d%d%d ",temp.x,temp.y,temp.z);
        for(int i=0;i<6;i++){
            //开始判断这几个位置
            int newx=temp.x+stepx[i];
            int newy=temp.y+stepy[i];
            int newz=temp.z+stepz[i];
           // printf("%d%d%d ",newx,newy,newz);
            if(judge(newx,newy,newz)){
                //如果这个合理的话,那就,把他的t加一,并且加入队列,这里创建了一个新的结构体,用来加入队列,还要出示话
                make[newx][newy][newz]=true;
                M gg;
                gg.x=newx;
                gg.y=newy;
                gg.z=newz;//找了半天,问题在这啊!!
                gg.t=temp.t+1;//这里是需要注意的
                //然后入队
                q.push(gg);
            }
        }

    }
    return -1;
}
int main()
{
    int k,time;
    scanf("%d",&k);
    while(k--){
       scanf("%d%d%d%d",&a,&b,&c,&time);
       //开始初始化
       for(int i=0;i<a;i++)
        for(int j=0;j<b;j++)
        for(int z=0;z<c;z++){
            scanf("%d",&map[i][j][z]);
            make[i][j][z]=false;
        }
        //然后开始先把第一个位置设置成访问过了
        make[0][0][0]=true;
        int re=BFS(0,0,0,0);
        if(re<=time)
        printf("%d\n",re);
        else
            printf("-1\n");
    }
    //debug发现从000出发之后,就一个点有效,然后之后就没用了,我知道了,还有一个k没有写!,然后还有问题。。


}

问题四:递归
在这里插入图片描述
这题有写过,在hdu100上面

问题五
素数环问题
在这里插入图片描述
在这里插入图片描述

题目大致意思:
在这里插入图片描述
这是一道好题,还是在看了解析之后写出来的,

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
#include<queue>
#include<stack>
using namespace std;
//素数环,大致思路就是:从1出发 然后输入一个值,判断这个值能不能和第一个值相加之后,仍然是素数,如果是的话,那就开始判断下一个
//如果不可以的话,那就回退到前一个
//需要创建一个数组来存当前的输入值,还有一个Bool型数组来判断当前这个可不可以用
int n;
int res[30];
bool has[30];
//再写一个方法判断这个数是不是素数
bool is_su(int x){
    if(x<=1)
        return false;
    for(int i=2;i<x;i++){
        if(x%i==0)
            return false;
    }
    return true;
}
//再写一个判断最后一个位置并且输出
void check(){
    if(!is_su(res[1]+res[n]))
        return ;//如果第一个和最后一个之和不是素数的话,直接回退
    for(int i=1;i<n;i++)
        printf("%d ",res[i]);
    printf("%d",res[n]);
    printf("\n");
}
void DFS(int num){
    //开始遍历
    if(num>1)
        if(!is_su(res[num]+res[num-1]))
        return ;//直接先判断这个可不可行
    if(num==n){
        //到了最后一个
        check();
        return ;
    }
    //其他情况开始
    for(int i=2;i<=n;i++){
        if(has[i]==false){
            //如果这个点没有被访问过,那就先把他变成访问
            has[i]=true;
            res[num+1]=i;//这里是+1 不代表num变成了num+1
            DFS(num+1);
            //开始遍历,遍历完了之后,在把这个位置设置为可以访问
            has[i]=false;
        }
    }

}
int main()
{
    int cas=0;//这个就是输出的时候那个case
    while(scanf("%d",&n)!=EOF){
        //输入这个N
        cas++;//每次都加一
        //初始化bool
        memset(has,false,sizeof(has));
        //然后开始判断,把第一个当做访问过了
        res[1]=1;
        has[1]=true;
        printf("Case %d\n",cas);
        DFS(1);

    }

}

下一题
在这里插入图片描述
题目大致意思:
在这里插入图片描述
其实就是求连通图的问题,可以用BFS和DFS,而用DFS比较适合,方法就是,在一个数组里,通过一次DFS,把它连通的@全都变成* 然后进行递归,找到剩余的@ 然后继续遍历

发布了88 篇原创文章 · 获赞 5 · 访问量 3531

猜你喜欢

转载自blog.csdn.net/qq_41115379/article/details/105195150