机试指南 cha6 搜索

机试指南 cha6 搜索

枚举
百鸡问题
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <map>
#include <string>
#define INFINITY 65535
using namespace std;

const int big = 5;
const int mid = 3;
const float small = 1/3;
int main()
{
    int n,x,y,z;
    while (cin>>n)
    {
        for (x = 0;x<=n/big;x++ )
            for (y=0;y<=n/mid;y++)
                for (z=0;z<=100;z++)
            {
                float tmp = big*x+mid*y+(float)z/3;
                if (x+y+z == 100 &&  tmp <= n)
                {
                    cout << "x="<<x<<",y="<<y<<",z="<<z<<endl;
                }
            }
    }

    return 0 ;
}

z 因为是1/3,

abc
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <map>
#include <string>
#define INFINITY 65535
using namespace std;

const int num = 532;
int cal(int a,int b,int c)
{
    return 100*a+10*b+c;
}
int main()
{
        int a,b,c;
        for (a = 0;a<=9;a++ )
            for (b=0;b<=9;b++)
                for (c=0;c<=9;c++)
            {
                int tmp = cal(a,b,c)+cal(b,c,c);
                if (tmp == num)
                {
                    cout <<a<<" "<<b<<" "<<c<<endl;
                }
            }


    return 0 ;
}

广搜
胜利大逃亡

提示内存不够:定义时不能多开辟数组空间,形成六面的“墙”,而是要判断是否超出边界的方式;提示运行时间过长,在把孩子结点加入队列后就立即判断是否是终止结点,而不是等到从队列中拿出的时候判断。这道题目的遗憾是1:自己通过思考做的方法就差一点巧妙的构思即可在本地通过编译;2. 牛客网的编译还是过不去,运行时间过长,不知道哪里的错误。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <map>
#include <string>
#define INFINITY 65535
using namespace std;
struct node
{
    int x,y,z;
    int t;
};
int room[50][50][50];
bool mark[50][50][50];
queue<node> q;

int dir[6][3] =
{
    {0,0,1},{0,1,0},{0,0,-1},{0,-1,0},{1,0,0},{-1,0,0}
};
int mazePath(node s,node &e,int a,int b,int c)
{
    node t,child;
    q.push(s); // 放入初始结点
    while (!q.empty())
    {
        t = q.front(); q.pop();//队头出队
        room[t.x][t.y][t.z] = 1; // 已经访问过则不再访问

        // 当前节点不为最终节点时,把当前节点的孩子结点入队
        for (int i=0;i<6;i++)
        {
            child = t;
            child.x += dir[i][0];
            child.y += dir[i][1];
            child.z += dir[i][2];
            // 下一个结点为墙
            if (room[child.x][child.y][child.z] == 1)
                continue;
            // 超出迷宫边界
            if (child.x < 0|| child.x >=a || child.y < 0|| child.y >=b || child.z < 0|| child.z >=c)
                continue;
            // 包含该坐标的状态已经被得到过,则丢弃
            if (mark[child.x][child.y][child.z] == true)
                continue;
            child.t ++;
            q.push(child);
            mark[child.x][child.y][child.z] = true; // 标记
            if (child.x == e.x && child.y == e.y && child.z == e.z)
            {
                return child.t;
            }

        }
    }
    return 0;
}

int main()
{
    int k,a,b,c,t,i,j,m,n;
    node start,end,ex;
    while (scanf("%d",&k)!=EOF)
    {
        for (i=0;i<k;i++)
        {
            scanf("%d%d%d%d",&a,&b,&c,&t);
            for (j=0;j<a;j++)
                for (m=0;m<b;m++)
                    for (n=0;n<c;n++)
                    {
                        scanf("%d",&room[j][m][n]);
                        mark[j][m][n] = false; // 初始化为false
                     }
           // (1,1,1) - > (a,b,c)
           start.x = 0;start.y=0;start.z=0;
           start.t = 0;
           mark[0][0][0] = true;
           end.x = a-1;end.y=b-1;end.z=c-1;
          while (!q.empty())
                q.pop();
          int ans = mazePath(start,end,a,b,c);
          if (ans <= t && ans > 0)
            cout << ans << endl;
          else
            cout << -1 << endl;



        }
    }
    return 0 ;
}


迷宫问题

严版数据结构课本的伪代码

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <stack>
#include <string>
using namespace std;

// 迷宫求解


// 结构体
typedef struct
{
    int x;
    int y;
    bool foot; // 是否走到过该通道
}posType;

typedef struct
{
    int ord;//通道块在路径上的序号
    posType seat; // 通道块在迷宫中的坐标
    int di;// 从此通道块走向下一通道块的方向
}elemType; // 栈的元素类型

// 全局变量声明
stack<elemType> s;
int a[6][6];

// 函数
void footPrint(posType p)
{
    p.foot = true;
}

bool pass(posType p)
{
    // 不可通的含义:不是通道;不在当前路径上;不是纳入路径上的通道块
    if (a[p.x][p.y] == 1)
        return false;
    else return true;

}

posType nextPos(posType p,int d)
{
    posType tmp;
    tmp.x = p.x+1;tmp.y = p.y+1;tmp.foot = p.foot;
    return tmp;
}

bool mazePath(int a[6][6],posType start,posType end)
{
    // 将从start到end的通道路径存放在栈中,找到路径返回true,否则返回false
    while (!s.empty())
        s.pop(); // initStack()
    posType curpos = start; // 把坐标封装起来
    elemType e;
    int curstep = 1; // 探索第一步
    do {
        if (pass(curpos)) // 是未曾走到过的通道块
        {
            footPrint(curpos); // 留下足迹
            e = {curstep,curpos,1}; // 1,2,3,4代表东南西北
            s.push(e);
            if (curpos == end)
                return true;
            curpos = nextPos(curpos,1);
            curstep++;
        }else {
        if (!s.empty())// 当前位置不能通过
        {
           e = s.top();s.pop();
           while (e.di == 4 && !s.empty())
           {
               markPrint(e.seat);//留下不能通过的标记
               s.pop();

           }
           if (e.di < 4)
           {
               e.di++;
               s.push(e);
               curpos = nextPos(e.seat,e.di);
           }
        }
        }
    }while (!s.empty());
    return false;

}
int main()
{
    int n,m,i,j;
    posType start,end;
    while (cin>>n>>m)
    {
        for (i=0;i<=5;i++)
            for (j=0;j<=5;j++)
            {
                if (i==0||j==0)
                    a[i][j] = 1;
                else
                    cin >> a[i][j];
            }
        // (1,1) -> (5,5) 最短路径 输出坐标
        end.x = 5;end.y=5;end.foot = false;
        start.x = 1;start.y=1;start.foot = false;
        mazePath(a,start,end);


    }
    return 0 ;
}

深搜

#include<iostream>
#include<string>
#include<list>
#define M 8
#define N 8
using namespace std;

/*
每次按照dir的方向进行深度优先搜索,可以走则走并标记,否则,
回溯并清除标记,直到找到右下角的出口。
*/

// 迷宫,Maze[i][j] = 0 代表ij可以走, arr[i][j]=1表示不能走
int Maze[M+2][N+2] = {
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
        {1, 0, 0, 0, 1, 1, 0, 1, 1, 1},
        {1, 1, 1, 0, 1, 1, 0, 1, 1, 1},
        {1, 1, 0, 0, 0, 0, 0, 1, 1, 1},
        {1, 1, 0, 0, 1, 1, 1, 0, 0, 1},
        {1, 1, 0, 0, 0, 0, 0, 0, 0, 1},
        {1, 1, 0, 1, 0, 1, 0, 0, 1, 1},
        {1, 0, 0, 1, 1, 1, 0, 0, 0, 1},
        {1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};

// 四个方向,分别代表上,下,左,右,这里注意x和y的方向和笛卡尔坐标系的方向相反
int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

// 节点信息,x代表横坐标,y代表纵坐标
struct Node
{
    int x;
    int y;
    // 初始化位置结点的构造函数
    Node (int x1, int y1){
    x = x1;y=y1;
    }
};


// 打印路径,使用链表,易于输出
void print_path(list<Node> path)
{
    while(!path.empty())
    {
        cout << "(" << path.front().x << "," << path.front().y << ")" << endl;
        path.pop_front(); // front()求链表头,pop_front()弹头,我感觉用vector也可以
    }
}

int DFS(Node cur, Node end, list<Node> &path) // 当前节点,出口
{
    Maze[cur.x][cur.y] = 1;     // 标记此节点已走过,设置为墙1
    path.push_back(cur);        // 将当前节点加入路径栈

    // 当前坐标等于结束坐标时结束遍历,并打印路径
    if(cur.x == end.x && cur.y == end.y)
    {
        print_path(path);       //打印路径
        return 1;
    }

    // 从4个方向分别探索
    for(int i = 0; i < 4; ++i)
    {
        // 构造下一个要进行探索的点
        Node next(cur.x + dir[i][0], cur.y + dir[i][1]);
        //  判断下个点是否可行
        if(Maze[next.x][next.y] == 0)
        {
            // 递归进行下一位置的查找
            // 如果一直可以先向下查找,直到找到终点,最底层函数就会返回1,接着返回到倒数第二层,执行if语句,接着返回1。
            // 直到跳出整个递归函数。
            if(DFS(next, end, path) == 1)
                return 1;
        }
    }

    // 如果该节点几个方向均已遍历,而且都不可行,该节点出栈,回溯
    path.pop_back();

    return 0;
}

int main( )
{
    list<Node> path;          // 存取路径,使用双向链表存储,Node为位置结点
    Node sta(1, 1), end(8, 8);  // 记录开始和结束坐标

    if(DFS(sta, end, path) == 0)
        cout << "no path" << endl;
}

广搜

#include <iostream>
#include <fstream>
#include <stack>
#include <vector>
#include <queue>
using namespace std;

const int MAX = 10;

struct node {
    int x,y,fx,fy;
    int content;
    bool visited;
};

node laby[MAX][MAX];

void BFS(int sx, int sy,int ex, int ey) {
    
    queue<node> myQueue;
    
    node temp = laby[sx][sy];
    myQueue.push(temp);
    
    int delx[4] = {0,0,-1,1};
    int dely[4] = {1,-1,0,0};

    while (!myQueue.empty()) {
        node currentNode = myQueue.front();
        
        myQueue.pop();
        
        int m = currentNode.x;
        int n = currentNode.y;
        
        currentNode.visited = true;
        
        if (currentNode.x == ex && currentNode.y == ey) {
            break;
        }
        
        for(int i = 0; i < 4;i++) {
            int next_m = m + delx[i];
            int next_n = n + dely[i];
            if (next_m < 0 || next_m >= MAX || next_n < 0 || next_n >= MAX) continue;
            
            if (laby[next_m][next_n].content != 1 && laby[next_m][next_n].visited == false) {
                laby[next_m][next_n].fx = m;
                laby[next_m][next_n].fy = n;
                myQueue.push(laby[next_m][next_n]);
                laby[next_m][next_n].visited = true;
            }
        }
    }
    
    int backx = ex, backy = ey;
    int step = 0;
    stack<node> showStack;
    
    while (backx != sx || backy != sy) {
        
        showStack.push(laby[backx][backy]);
        
        int tempBackx = laby[backx][backy].fx;
        int tempBacky = laby[backx][backy].fy;
        
        backx = tempBackx;
        backy = tempBacky;

        step++;
    }
    
    cout<<"Path:"<<endl;
    while (!showStack.empty()) {
        node current = showStack.top();
        showStack.pop();
        cout<<'('<<current.x<<','<<current.y<<") ";
    }
    cout<<endl;
    
    cout<<"total steps:"<<step<<endl;
}


int main(int argc, const char * argv[]) {
    
    ifstream in;
    in.open("laby.txt",ios::in);
    
    if (!in) {
        cerr<<"file not existed!"<<endl;
        exit(1);
    }
    
    int sx,sy,ex,ey;
    
    int curNum;
    int m = 0, n = 0;
    
    while (!in.eof()) {
        in>>curNum;
        laby[m][n].content = curNum;
        laby[m][n].x = m;
        laby[m][n].y = n;
        laby[m][n].visited = false;
        if (curNum == 5) {
            sx = m;
            sy = n;
        }
        if (curNum == 8) {
            ex = m;
            ey = n;
        }
        n ++;
        if (n == MAX) {
            n = 0;
            m++;
        }
    }
    
    for(int i = 0; i < MAX; i++) {
        for(int j = 0; j < MAX; j++) {
            cout<<laby[i][j].content<<" ";
        }
        cout<<endl;
    }
    cout<<endl;
    
    BFS(sx, sy, ex, ey);
    return 0;
}

虚拟队列 求最短的路径

#include <iostream>  
#include <vector>  
#include <stack>  
#define M 8  
#define N 8  
  
using namespace std;  
  
// 迷宫,Maze[i][j] = 0 代表ij可以走, arr[i][j]=1表示不能走  
int Maze[M+2][N+2] = {  
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},  
        {1, 0, 0, 0, 1, 1, 0, 1, 1, 1},  
        {1, 1, 1, 0, 1, 1, 0, 1, 1, 1},  
        {1, 1, 0, 0, 0, 0, 0, 1, 1, 1},  
        {1, 1, 0, 0, 1, 1, 1, 0, 0, 1},  
        {1, 1, 0, 0, 0, 0, 0, 0, 0, 1},  
        {1, 1, 0, 1, 0, 1, 0, 0, 1, 1},  
        {1, 0, 0, 1, 1, 1, 0, 0, 0, 1},  
        {1, 1, 1, 1, 1, 1, 1, 1, 0, 1},  
        {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}  
};  
  
  
// 节点信息,x代表横坐标,y代表纵坐标  
struct Node  
{  
    int x;  
    int y;  
    Node (int x1, int y1):x(x1), y(y1) {}  
};  
  
// 虚拟队列中的节点及其前驱信息  
struct QueueElem  
{  
    int pre;        // 该节点入队时的前驱节点在虚拟队列中的位置  
    Node node;  
    QueueElem(Node node1, int pre1):node(node1), pre(pre1) {}  
};  
  
void print_path(vector<QueueElem> &que)  
{  
    stack<QueueElem> s;  
  
    QueueElem qe = que.back();  
    while(qe.pre != -1)  
    {  
        s.push(qe);  
        qe = que[qe.pre];  
    }  
  
    while(!s.empty())  
    {  
        qe = s.top();  
        s.pop();  
        cout << "(" << qe.node.x << "," << qe.node.y << ")" << endl;  
    }  
}  
  
  
void maze_shortest(Node start, Node des)  
{  
    int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};  
    vector<QueueElem> que;                  // 用于记录节点入队顺序  
    int head = 0;                           // 用于指向队列头部  
  
    que.push_back(QueueElem(start, -1));    // 初始点入队,其前驱为-1  
    while(head < que.size())                // 当虚拟队列非空时  
    {  
        Node cur = que[head].node;  
  
        for(int i = 0; i < 4; ++i)  
        {  
            Node next(cur.x + dir[i][0], cur.y + dir[i][1]);  
  
            if(Maze[next.x][next.y] == 0)   // 下一节点可走  
            {  
                // 下一节点入队  
                que.push_back(QueueElem(next, head));  
                if(next.x == des.x && next.y == des.y)  
                {  
                    print_path(que);  
                    return;  
                }  
            }  
        }  
        head++;         // 虚拟出队  
    }  
}  
  
  
int main()  
{  
    Node start(1, 1), des(8, 8);    // 记录开始和结束坐标  
  
    maze_shortest(start, des);  
}  
2018/5/16 搜索

迷宫问题

这道题做的时候是自己独立思考出来的,但最后却花了更多的时间在调试错误上面,这个OJ用了两个月了,为什么这么基础的问题还要不断的犯错误呢?但调试功底见长是真的,耗时长也是真的,所有的耗时长都是因为练习不够。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stack>
#include <queue>
using namespace std;

struct node
{
    int x,y;
};
int a[12][12];
int dir[4][2] =
{// 东南西北
    {0,1},{1,0},{0,-1},{-1,0}
};
queue<node> st;
void printPath();
int mazePath(node s,node e)
{
    node next = s;
    int ans ;
    a[s.x][s.y] = 1;//表示该结点已经走过,记为墙
    // 先判断当前节点是否为最终节点
    if (s.x == e.x && s.y == e.y)
    {
        printPath();
       return 1;
    }

    // 当前节点不等于最终节点,最理想的状态是一直往东走
    for (int i=0;i<4;i++)
    {
        // 向四个方向走一步,递归
        next = s;
        next.x += dir[i][0];
        next.y += dir[i][1];
        if (a[next.x][next.y] == 0){ // 能走通则压栈,继续走
            st.push(next);
            ans  = mazePath(next,e);
            if (ans == 1)
                return 1;
        }

    }
    // 如果这一层的四个方向均走不通,出栈
        st.pop();
        return 0;
}

void printPath()
{
    node t;
    while (!st.empty())
    {
        t = st.front();
        cout << "(" << t.x-1<<","<<t.y-1<<")"<<endl;
        st.pop();
    }
}
void printA(int n,int m)
{
    for (int i=0;i<=n;i++)
    {
        for (int j=0;j<=m;j++)
            cout << a[i][j] <<" ";
        cout << endl;
    }

}
int main()
{
    int n,m,i,j;
    node start,end;
    while (cin>>n>>m{

        for (i=0;i<=n+1;i++)
            for (j=0;j<=m+1;j++)
            {// 四周筑墙
                if (i==0||j==0 || i==(n+1) || j==(m+1))
                    a[i][j] = 1;
                else
                    cin >> a[i][j];
            }
        // (1,1) -> (5,5) 最短路径 输出坐标
        start.x = 1;start.y=1;
        end.x = n;end.y=m;
        while (!st.empty())
            st.pop();
        st.push(start);
        mazePath(start,end);
}



    return 0 ;
}

北航机试题

C翻转

这是一道找规律的题目。temp数组的设置比较巧妙。
原矩阵:
1 2 3
4 5 6
7 8 9
顺时针旋转:
7 4 1
8 5 2
9 6 3
数组i=0的变化:
11 - 13
12 - 23
13 - 33
数组i=1的变化:
21 - 12
22 - 22
23 - 32
数组i=3的变化
31 - 11
32 - 21
33 - 31

原矩阵:
1 2 3
4 5 6
7 8 9
逆时针旋转:
3 6 9
2 5 8
1 4 7
数组i=0的变化:
11 - 31
12 - 21
13 - 11
数组i=1的变化:
21 - 32
22 - 22
23 - 12
数组i=3的变化
31 - 33
32 - 23
33 - 13

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <map>
#include <string>
#define INFINITY 65535
using namespace std;

int a[6][6];

void reverse(int op1,int op2,int x,int y)
{
    // op1 : 1 顺时针 op2 :2为4个数,3为9个数, 以(x,y)为左上角翻转op2^2个数
    int i,j,temp[op2+1][op2+1];
    for (i=1;i<=op2;i++)
        for (j=1;j<=op2;j++)
    {
        if (op1 == 1)
        {
            // 顺时针。按照一行一行从左到右的顺序,依次放入temp中转置后应该在的位置
            temp[j][op2+1-i] = a[x+i-1][y+j-1];
        }
        else
        {
            temp[op2+1-j][i] = a[x+i-1][y+j-1];
        }
    }
    // 现在temp数组中即为转置后的数组顺序,只要赋值到a中相应的位置并输出即可
    for (i=x;i<x+op2;i++)
        for (j=y;j<y+op2;j++)
            a[i][j] = temp[i-x+1][j-y+1];
}

int main()
{
    int i,j,op1,op2,x,y;
    for (i=1;i<=5;i++)
        for (j=1;j<=5;j++)
            cin >> a[i][j];
    cin >> op1 >> op2 >> x >> y;
    reverse(op1,op2,x,y);
    for (i=1;i<6;i++)
    {
        for (j=1;j<6;j++)
        {
            cout << a[i][j]<< " ";
        }
        cout << endl;
    }


    return 0 ;
}

旋转矩阵

这道题我的第一个想法是:把第一个矩阵旋转四个角度,看得到的矩阵是否和第二个矩阵相等,但是这样太麻烦了!判断标准有两个,正确旋转结果相同或者存在一个错误旋转结果,则直接否定该种旋转方案。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <map>
#include <string>
#define INFINITY 65535
using namespace std;

int a[10][10],b[10][10];
int main()
{
    int n,i,j;
    bool flag[4] = {true,true,true,true};  // 0 90 180 270
    cin >> n;
    for (i=0;i<n;i++)
        for (j=0;j<n;j++)
            cin >> a[i][j];
    for (i=0;i<n;i++)
        for (j=0;j<n;j++)
            cin >> b[i][j];

    for (i=0;i<n;i++)
        for (j=0;j<n;j++)
    {
        // 对所有的a[i][j]进行判别
        if (a[i][j] != b[i][j])
            flag[0] = false;
        if (a[i][j] != b[j][n-1-i])
            flag[1] = false;
        if (a[i][j] != b[n-1-i][n-1-j])
            flag[2] = false;
        if (a[i][j] != b[n-1-j][i])
            flag[3] = false;
    }

    for (i=0;i<4;i++)
        if (flag[i] == true)
    {
        cout << i*90 << endl;
        return 0 ;
    }
    cout << -1 << endl;
    return 0 ;
}

字符串匹配
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <map>
#include <string>
#include <string.h>
#define INFINITY 65535
using namespace std;

string a[1000];
string lower(string a)
{
    for (int i=0;i<a.length();i++)
    {
        if (a[i]>= 'A' && a[i] <= 'Z')
            a[i] = a[i] - 'A'+'a';
    }
    return a;
}
void match(int n,string b)
{
    for (int i=0;i<n;i++)
    {
        if (lower(b) == lower(a[i]))
        {
          cout << i+1 << " " << a[i]<<endl;
        }
    }
}
int main()
{
    int n,i;
    string b, m, tmp1, tmp2, new1;
    while (cin>>n)
    {
        for (i=0;i<n;i++)
            cin >> a[i];
        cin >> b;
        // b中可以有一个模式匹配,中括号内的字符中的任意一个即可
        int pos1 = b.find("["); // 找到返回索引,否则返回-1
        int pos2 = b.find("]"); // 找到返回索引,否则返回-1

        if (pos1 == -1 )
        {
            match(n,b);
        }
        else
        {
            m = b.substr(pos1+1,pos2-pos1-1);
            tmp1 = b.substr(0,pos1);
            tmp2 = b.substr(pos2+1,b.length()-pos2);
            for (i=0;i<m.length();i++)
            {
                new1 = tmp1+m[i]+tmp2;
                match(n,new1);
            }
        }


    }
    return 0 ;
}

通过率大概百分之18,题目描述地不太清楚。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值