220128总结

220128总结

被卡深搜的一天

  1. 面积(Area)

    昨天原题直接复制(

  2. 营救(Save)

    【问题描述】
    铁塔尼号遇险了!他发出了求救信号。距离最近的哥伦比亚号收到了讯息,时间就是生命,必须尽快
    赶到那里。
    通过侦测,哥伦比亚号获取了一张海洋图。这张图将海洋部分分化成 n个比较小的单位,其中用 1
    标明的是陆地,用 0 标明是海洋。船只能从一个格子,移到相邻的四个格子。
    为了尽快赶到出事地点,哥伦比亚号最少需要走多远的距离。
    【输入格式】
    第一行为 n,下面是一个 n 的 0、1 矩阵,表示海洋地图
    最后一行为四个小于 n 的整数,分别表示哥伦比亚号和铁塔尼号的位置。
    【输出格式】
    哥伦比亚号到铁塔尼号的最短距离,答案精确到整数。
    【输入样例】
    3
    001
    101
    100
    1 1 3 3
    【输出样例】
    4
    【数据范围】
    N<=1000

    广搜最先到达的就是最短的路径

    void BFS(){
    	queue<pair<int,int> > A;
    	A.push(make_pair(frx,fry));
    	queue<int>steps;
    	steps.push(1);
    	while(!A.empty()){
    		int ns = 0;
    		for(int i = 0;i<4;i++){
    			int xx = A.front().first + F[i][0];
    			int yy = A.front().second + F[i][1];
    			step += 1;
    			if(xx > n || xx < 1) continue;
    			if(yy > n || yy < 1) continue;
    			if(map_[xx][yy] == 1) continue;
    			if(xx == tox && yy == toy) printf("%d",steps.front());
    			A.push(make_pair(xx,yy));
    			steps.push(steps.front()+1);
    			map_[xx][yy] = 1;
    		}
    		A.pop();
    		steps.pop();
    	}
    }
    
  3. 最少转弯问题(turn)

    【问题描述】

    给出一张地图,这张地图被分为\(n\times m(n,m\leqslant 100)\)个方块,任何一个方块不是平地就是高山。平地可以通过,高山则不能。现在你处在地图的\((x_1,y_1)\)这块平地,问:你至少需要拐几个弯才能到达目的地\((x_2,y_2)\)?你只能沿着水平和垂直方向的平地上行进,拐弯次数就等于行进方向的改变(从水平到垂直或从垂直到水平)的次数。例如:如图,最少的拐弯次数为5。

    img

    【输入格式】

      第一行:n和m。
      第二至n+1行:一个矩阵,为地图。(0:空地;1:高山。)
      第n+2行:x1,y1,x2和y2。

    【输出格式】

      只有一行,为最少的转弯次数。

    【样例输入】

    5 7
    1 0 0 0 0 1 0
    0 0 1 0 1 0 0
    0 0 0 0 1 0 1
    0 1 1 0 0 0 0
    0 0 0 0 1 1 0
    1 3 1 7

    【样例输出】

    5

    这题我写得不太严谨(可是996上的数据真的很水,没有考虑两次到达同一点的情况

    宽搜时最先到达一个点时一定是最短路径但不一定是最少转弯

    正解可以参考T4

  4. 在一种"麻将"游戏中,游戏是在一个有 w*h 格子的矩形平板上进行的。每个格子可以放
    置一个麻将牌,也可以不放(如图所示)。玩家的目标是将平板上的所有可通过一条路径相
    连的两张相同的麻将牌,从平板上移去。最后如果能将所有牌移出平板,则算过关。
    这个游戏中的一个关键问题是:两张牌之间是否可以被一条路径所连接,该路径满足以
    下两个特性:

    1. 它由若干条线段组成,每条线段要么是水平方向,要么是垂直方向。

    2. 这条路径不能横穿任何一个麻将牌 (但允许路径暂时离开平板)。

      img


      这是一个例子。

      在(1,3)的牌和在(4, 4)的牌可以被连接。(2, 3)和(3, 4)不能被连接。

      你的任务是编一个程序,检测两张牌是否能被一条符合以上规定的路径所连接。

    【输入格式】

    第一行有两个整数\(w,h(1\leqslant w,h\leqslant 75)\),表示平板的宽和高。接下来h行描述平板信息,每行包含w个字符,如果某格子有一张牌,则这个格子上有个'X',否则是一个空格。平板上最左上角格子的坐标为\((1,1)\),最右下角格子的坐标为\((w,h)\)。接下来的若干行,每行有四个数\(x1,y1,x2,y2\) ,且满足\(1\leqslant x1,x2 \leqslant w\)\(1\leqslant y1,y2\leqslant h\),表示两张牌的坐标(这两张牌的坐标总是不同的)。如果出现连续四个0,则表示输入结束。

    【样例输入】(0代表空格)
    5 4
    XXXXX
    X000X
    XXX0X
    0XXX0
    2 3 5 3
    1 3 4 4
    2 3 3 4
    0 0 0 0
    【样例输出】
    4
    3
    0

    这真的不是连连看吗

    基本思路就是宽搜

    不过需要尽可能多地走直线,因为要求的是最小转弯数

    那么就按一个方向一直走下去,直到出范围或者遇上其他麻将

    如果遇上的一个位置是曾经走到过的位置

    #include<bits/stdc++.h>
    using namespace std;
    
    int map_[100][100];
    int F[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
    int w,h;
    
    struct node{
    	int x,y;
    	int depth;
    };
    int BFS(int stx,int sty,int tox,int toy){
    	queue<node> A;
    	int canGo[100][100];
    	memset(canGo,0,sizeof(canGo));
    	node a;
    	a.x = stx;
    	a.y = sty;
    	a.depth = 0;
    	A.push(a);
    	while(!A.empty()){
    		a = A.front();
    		A.pop();
    		for(int i = 0;i<4;++i){
    			int tx = a.x + F[i][0];
    			int ty = a.y + F[i][1];
    			//四个方向都走到头 
    			while(true){
    				//出框了就停 
    				if(tx < 1 || tx > h+2) break;
    				if(ty < 1 || ty > w+2) break;
    				//这个点曾经到达过且这个点深度比当前大1(即下一步会走到且两次走到该点的步数相同)就停 
    				if(!(canGo[tx][ty] == 0 || canGo[tx][ty] == a.depth +1)) break;
    			 	//到达目标点就返回值 
    				if(tx == tox && ty == toy) return a.depth+1;
    				//如果该点为不可走就停止 
    				//这句和上句判断到达目标点不可调序,因为目标点不可走 
    				if(map_[tx][ty] == -1) break;
    				//在地图上留下到达该点所耗步数 
    			 	canGo[tx][ty] = a.depth+1;
    			 	//将这个点入队 
    			 	node b;
    			 	b.x = tx;
    			 	b.y = ty;
    			 	b.depth = a.depth+1;
    			 	A.push(b);
    			 	tx += F[i][0];
    			 	ty += F[i][1];
    			}
    		}
    	}
    	return 0;
    }
    
    int main(){
    	scanf("%d%d",&w,&h);
    	memset(map_,-1,sizeof(map_));
    	for(int i = 1;i<h+3;i++){
    		map_[i][1] = 0;
    		map_[i][w+2] = 0;
    	}
    	for(int i = 1;i<w+3;i++){
    		map_[1][i] = 0;
    		map_[h+2][i] = 0;
    	}
    	getchar();
    	for(int i = 2;i<h+2;i++){
    		for(int j = 2;j<w+2;j++){
    			char c;
    			c = getchar();
    			map_[i][j] = (c == 'X')?-1:0;
    		}
    		getchar();
    	}
    	while(true){
    		int x,y,xx,yy;
    		scanf("%d%d%d%d",&y,&x,&yy,&xx);
    		if(x == 0 && y == 0 && xx == 0 && yy == 0) break;
    		int ds = BFS(x+1,y+1,xx+1,yy+1);
    		printf("%d\n",ds);
    	}
    	return 0;
    }
    //5 4
    //XXXXX
    //X   X
    //XXX X
    // XXX 
    //2 3 5 3
    //1 3 4 4
    //2 3 3 4
    //0 0 0 0
    
    
posted @ 2022-01-28 16:01  Burnling  阅读(54)  评论(0编辑  收藏  举报