[NWPU][2014][TRN][3]搜索 总结

来源:互联网 发布:java导出至excel表格 编辑:程序博客网 时间:2024/05/19 17:27
这次总共就作出了五道题,后边的几道暂时还没什么思路。
A -
广搜 基础
Time Limit:2000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u

Description

Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a pointN (0 ≤N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer John has two modes of transportation: walking and teleporting.

* Walking: FJ can move from any point X to the points X - 1 orX+ 1 in a single minute
* Teleporting: FJ can move from any point X to the point 2 × X in a single minute.

If the cow, unaware of its pursuit, does not move at all, how long does it take for Farmer John to retrieve it?

Input

Line 1: Two space-separated integers: N andK

Output

Line 1: The least amount of time, in minutes, it takes for Farmer John to catch the fugitive cow.

Sample Input

5 17

Sample Output

4

Hint

The fastest way for Farmer John to reach the fugitive cow is to move along the following path: 5-10-9-18-17, which takes 4 minutes.

这道题比较简单,让N通过加减1或自身乘2地方式最终得到K。直接广搜即可。直接AC了当时。


#include <cstdio>#include <queue>using namespace std;const int MAXN = 100001;int N, K;int vis[MAXN];int ret[MAXN];queue<int> q;int BFS(int s, int d){if (s == d) return 0;q.push(s);int cur;while (!q.empty()){cur = q.front();q.pop();if (cur + 1 < MAXN && !vis[cur + 1]){q.push(cur + 1);ret[cur + 1] = ret[cur] + 1;vis[cur + 1] = 1;}if (cur + 1 == d) break;if (cur - 1 >= 0 && !vis[cur - 1]){q.push(cur - 1);ret[cur - 1] = ret[cur] + 1;vis[cur - 1] = 1;}if (cur - 1 == d) break;if (cur*2 < MAXN && !vis[cur *2]){q.push(cur *2);ret[cur *2] = ret[cur] + 1;vis[cur *2] = 1;}if (cur *2 == d) break;}return ret[d];}int main(){scanf("%d %d", &N,&K);printf("%d\n", BFS(N, K));return 0;}


B - 广搜/深搜 基础
Time Limit:1000MS    Memory Limit:30000KB    64bit IO Format:%I64d & %I64u

Description

There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A man is standing on a black tile. From a tile, he can move to
 one of four adjacent tiles. But he can't move on red tiles, he can move only on black tiles.

Write a program to count the number of black tiles which he can reach by repeating the moves described above.

Input

The input consists of multiple data sets. A data set starts with a line containing two positive integers W and H; W and H are the numbers of tiles in
 the x- and y- directions, respectively. W and H are not more than 20.

There are H more lines in the data set, each of which includes W characters. Each character represents the color of a tile as follows.

'.' - a black tile
'#' - a red tile
'@' - a man on a black tile(appears exactly once in a data set)
The end of the input is indicated by a line consisting of two zeros.

Output

For each data set, your program should output a line which contains the number of tiles he can reach from the initial tile (including itself).

Sample Input

6 9....#......#..............................#@...#.#..#.11 9.#..........#.#######..#.#.....#..#.#.###.#..#.#..@#.#..#.#####.#..#.......#..#########............11 6..#..#..#....#..#..#....#..#..###..#..#..#@...#..#..#....#..#..#..7 7..#.#....#.#..###.###...@...###.###..#.#....#.#..0 0

Sample Output

4559613
从起点‘@’出发不能通过‘#’求出可以走到的‘.’的数量。第一次时,总是在第三个测试数据时无法通过,结果总是把所以的点都走了一遍,后来从写了一遍代码,就可以AC了,
可能是判断时出现了错误(实际我找了半天没找到)。
#include <stdio.h>#include <string.h>int n,m,cnt;char map[30][30];int to[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};void dfs(int i,int j){    cnt++;    map[i][j] = '#';    for(int k = 0; k<4; k++)    {        int x = i+to[k][0];        int y = j+to[k][1];        if(x<n && y<m && x>=0 && y>=0 && map[x][y] == '.')            dfs(x,y);    }    return;}int main(){    int i,j,fi,fj;    while(~scanf("%d%d%",&m,&n))    {        if(m == 0 && n == 0)            break;        for(i = 0; i<n; i++)        {            for(j = 0; j<m; j++)            {                scanf(" %c",&map[i][j]);//%c前边有个空格,要不把回车读进去了                if(map[i][j] == '@')                {                    fi = i;                    fj = j;                }            }        }        cnt = 0;        dfs(fi,fj);        printf("%d\n",cnt);    }    return 0;}

C - 广搜 基础
Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u

Description

A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visits each square of
a given set of n squares on a chessboard exactly once. He thinks that the most difficult part of the problem is determining the smallest number of knight
 moves between two given squares and that, once you have accomplished this, finding the tour would be easy.
Of course you know that it is vice versa. So you offer him to write a program that solves the "difficult" part.

Your job is to write a program that takes two squares a and b as input and then determines the number of knight moves on a shortest route from a to b.

Input

The input will contain one or more test cases. Each test case consists of one line containing two squares separated by one space. A square is a string consisting
of a letter (a-h) representing the column and a digit (1-8) representing the row on the chessboard.

Output

For each test case, print one line saying "To get from xx to yy takes n knight moves.".

Sample Input

e2 e4a1 b2b2 c3a1 h8a1 h7h8 a1b1 c3f6 f6

Sample Output

To get from e2 to e4 takes 2 knight moves.To get from a1 to b2 takes 4 knight moves.To get from b2 to c3 takes 2 knight moves.To get from a1 to h8 takes 6 knight moves.To get from a1 to h7 takes 5 knight moves.To get from h8 to a1 takes 6 knight moves.To get from b1 to c3 takes 1 knight moves.To get from f6 to f6 takes 0 knight moves.
马踏棋盘的问题,找两个点的最少行进次数,本来这题应该是广搜的,结果我没注意标题,(其实我当时也分不清什么是深搜什么是广搜)直接套着B题的深搜也过了。⊙﹏⊙
#include <cstdio>#include <string>#include <cstring>using namespace std;const int dir[8][2]= {1,2,1,-2,-1,2,-1,-2,2,1,2,-1,-2,1,-2,-1};const int N = 10;char ch1, ch2, ch3, ch4;int x1, y1, x2, y2;int used[N][N];void DFS(int x, int y, int t){    if(x>7||x<0||y>7||y<0||used[x][y]<=t)        return;    used[x][y]=t;    for (int i = 0; i < 8; i++)    {        int tx=x+dir[i][0];        int ty=y+dir[i][1];        DFS(tx,ty,t+1);    }}int main(){    while (scanf("%c%c %c%c", &ch1, &ch2, &ch3, &ch4) != EOF)    {        getchar();        x1 = ch1 - 'a', y1 = ch2 - '1';        x2 = ch3 - 'a', y2 = ch4 - '1';        for (int i = 0; i < 8; i++)            for (int j = 0; j < 8; j++)                used[i][j] = 64;        DFS(x1, y1, 0);        printf("To get from %c%c to %c%c takes %d knight moves.\n", ch1, ch2, ch3, ch4, used[x2][y2]);    }}


D - 广搜 基础
Time Limit:1000MS    Memory Limit:30000KB    64bit IO Format:%I64d & %I64u

Description

Background
Mr Somurolov, fabulous chess-gamer indeed, asserts that no one else but him can move knights from one position to another so fast. Can you beat him?
The Problem
Your task is to write a program to calculate the minimum number of moves needed for a knight to reach one point from another, so that you have the chance
to be faster than Somurolov.
For people not familiar with chess, the possible knight moves are shown in Figure 1.

Input

The input begins with the number n of scenarios on a single line by itself.
Next follow n scenarios. Each scenario consists of three lines containing integer numbers. The first line specifies the length l of a side of the chess board
 (4 <= l <= 300). The entire board has size l * l. The second and third line contain pair of integers {0, ..., l-1}*{0, ..., l-1} specifying the starting and ending
position of the knight on the board. The integers are separated by a single blank. You can assume that the positions are valid positions on the chess
board of that scenario.

Output

For each scenario of the input you have to calculate the minimal amount of knight moves which are necessary to move from the starting point to the ending point.
 If starting point and ending point are equal,distance is zero. The distance must be written on a single line.

Sample Input

380 07 01000 030 50101 11 1

Sample Output

5280
这题我按照上一题的套路,直接跪了,才注意是广搜。这里又错了一次,忘了全局变量的队列,没有清空造成了错误。
#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<queue>using namespace std;const int MAXN = 600;struct point{    int x;    int y;    int dis;};int vis[MAXN][MAXN];int X[8]={-2,-2,-1,-1,2,2,1,1}; int Y[8]={-1,1,-2,2,-1,1,-2,2};int bfs();int cango(int i,int j);  int n;   queue<point>myqueue;  point start,end;    int main(){    int t;    scanf("%d",&t);    while (t--)    {        scanf("%d",&n);        memset(vis,0,sizeof(vis));        scanf("%d%d",&start.x,&start.y);        scanf("%d%d",&end.x,&end.y);        if(start.x == end.x && start.y == end.y)        {            printf("0\n");            continue;        }        while(!myqueue.empty())  //清空队列,因为队列是全局的,要不就跪了                                        myqueue.pop();        printf("%d\n",bfs());    }    return 0;}int bfs(){    start.dis = 0;      myqueue.push(start);    vis[start.x][start.y] = 1;     point temp,next;    while (!myqueue.empty())    {        temp = myqueue.front();        myqueue.pop();        int k;        for(k=0;k<8;k++)        {            next.x = temp.x+X[k];            next.y = temp.y+Y[k];            if(cango(next.x,next.y))            {                next.dis = temp.dis + 1;                if(next.x == end.x && next.y == end.y)                return next.dis;                myqueue.push(next);                vis[next.x][next.y] = 1;            }        }    }}int cango(int i,int j){    if(i>=0&&i<n&&j>=0&&j<n&&vis[i][j]==0)    return 1;    return 0;}

E - 广搜记录路径 基础
Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%I64d & %I64u
SubmitStatus

Description

定义一个二维数组:
int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0,};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

Input

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

Output

左上角到右下角的最短路径,格式如样例所示。

Sample Input

0 1 0 0 00 1 0 1 00 0 0 0 00 1 1 1 00 0 0 1 0

Sample Output

(0, 0)(1, 0)(2, 0)(2, 1)(2, 2)(2, 3)(2, 4)(3, 4)(4, 4)
这个最大的问题是当时不知道怎么记录路径和怎么输出。
记录路径是用一个数组记录当前状态之前的状态,输出是用的是递归调用。搞明白这两个后这题就搞定了。

#include<stdio.h>#include<string.h>#include<stdlib.h>int map[5][5];int visit[5][5];int pre[100];  //记录每一个状态的前一个状态struct cam{int x;int y;}list[100];int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};int go(int x,int y){if(0<=x&&x<5&&0<=y&&y<5&&map[x][y]==0)return 1;return 0;}void print(int x){int t;t=pre[x];    if(t==0){printf("(0, 0)\n");        printf("(%d, %d)\n",list[x].x,list[x].y);return;}elseprint(t);    printf("(%d, %d)\n",list[x].x,list[x].y);}void bfs(){int i,head,tail;int x,y,xx,yy;memset(visit,0,sizeof(visit));    head=0;tail=1;    list[0].x=0;list[0].y=0;pre[0]=-1;while(head<tail){x=list[head].x;y=list[head].y;if(x==4&&y==4){            print(head);return;}for(i=0;i<4;i++){xx=x+dir[i][0];yy=y+dir[i][1];if(!visit[xx][yy]&&go(xx,yy)){visit[xx][yy]=1;list[tail].x=xx;list[tail].y=yy;pre[tail]=head;tail++;}}head++;}return;}int main(){int i,j;for(i=0;i<5;i++)for(j=0;j<5;j++)scanf("%d",&map[i][j]);bfs();return 0;}



0 0
原创粉丝点击