FZU 1275和UVA11624

這兩個題比較相似,放到一起來整理。

FZU 1275
放火燒山

法外狂徒張三在n*m的平地上放火玩,#表示草,張三有分身,他的分身和他本人分別選一個#格子點火,火可以向上向下向左向右在有草的格子蔓延,點火的地方時間爲0,蔓延至下一格的時間依次加一。求燒完所有的草需要的最少時間。如不能燒完輸出-1。

第一行,輸入一個T,表示有T組測試數據。
每組數據由一個n,m分別表示行列
1 <= T <=100, 1 <= n <=10, 1 <= m <=10

思路:基本就是廣度優先搜素,由於數據量不大,可以任意尋找合適的點來bfs。bfs的內容就是計算從這兩個點出發燒完所有草的時間,然後更新。

代碼:

#include <iosream>
#include <string>
#include <queue>
using namespace std;
const int INF=1e5;
int step[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int board[11][11]; // map
int cost[11][11]; // 花費的時間
int visit[11][11]; // 這個點有沒有訪問到
int ans=INF;
int m,n;
void get_ans() // 更新最值的函數
{
    int res=-1;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(board[i][j] &&!visit[i][j])
            	return;	
            	if(board[i][j] && cost[i][j]>res) res=cost[i][j];
        }
    }
    if(res<ans) res=ans;
}
void bfs(int x1,int y1,int x2,int y2)
{
    for(int i=0;i<m;i++)
    		for(int j=0;j<n;j++)
    		{
    		    cost[i][j]=-1,visit[i][j]=0;
    		}
    	queue< pair<int,int> >q; // 要注意這個用法
    	q.push(pair<int,int>(x1,y1)); // push進去
    	visit[x1][y1]=1;
    	cost[x1][y1]=0; // 初始化
    	if(!visit[x2][y2]){
    	    q.push(pair<int,int>(x2,y2));
    	    cost[x2][y2]=0;
    	    visit[x2][y2]=1;
    	}
    	while(!q.empty()){
    	    pair<int,int> t=q.front();
    	    q.pop();
    	    for(int i=0;i<4;i++){ // 關鍵循環
    	        int x=t.first; int y=t.second; // x位置,y位置
    	        x+=step[i][0];y+=step[i][1];
    	        if(x>=0&&x<m&&y>=0&&y<n&&!visit[x][y]&&board[x][y]){
    	            visit[x][y]=1;
    	            cost[x][y]=cost[t.first][t.second]+1;
    	            q.push(pair<int,int>(x,y)); // 合適的點就進隊列
    	        } 
    	    }
    	}
    	get_ans();
    	// 每次bfs都要更新
}
int main()
{
    int t;
    cin>>t;
    for(int k=1;k<=t;k++)
    {
        cin>>m>>n;
        for(int i=0;i<m;i++)
        {
            string s;
            cin>>s;
            for(int j=0;j<n;j++)
            { // 這裏不用原來的輸入,轉化成數字
                if(s[j]=='#') board[i][j]=1;
                else board[i][j]=0;
            }
        }
        for(int i=0;i<m;i++)
        for(int j=0;j<n;j++)
        for(int p=0;p<m;p++)
        for(int q=0;q<n;q++)
	        bfs(i,j,p,q); // 數據量比較小,暴力
        if(ans!=inf) printf("Case %d: %d\n",k,ans);
        else printf("Case %d: -1\n",t);
        ans=INF;
    }
}

UVA 11624
喬在迷宮中工作。不幸的是,迷宮的一部分着火了,迷宮的主人沒有制定火災的逃跑計劃。請幫助喬逃離迷宮。根據喬在迷宮中的位置以及迷宮的哪個方塊着火,你必須確定火焰燒到他之前,喬是否可以離開迷宮,如果能離開他能跑多快。
喬和火每分鐘移動一個方格,上、下、左、右,四個方向中的一個。火勢向四個方向同時蔓延。喬可以從迷宮的任何一個邊界逃離迷宮。無論是喬還是火都不會到達有牆的位置。

Input
第一行輸入包含一個整數,即測試次數
每個測試用例的第一行包含兩個
整數R和C,用空格分隔,1≤R,C≤1000
下面R行中,每一行都包含C個字符,以及每個字符是以下之一:# 代表牆
. 代表空地,火和喬是可通行的
J 喬在迷宮中最初的位置,火和喬是可通行的
F 代表火
在每組測試中只有一個J

思路:雙bfs,喬和火兩個bfs同步進行。

// UVa 11624 Fire
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int INF = 1e5;
int step[4][2]={{-1,0},{1,0},{0,-1},{0,1} };
int maze[1005][1005];
int cost_by_F[1005][1005];
int cost_by_J[1005][1005];
int visit[1005][1005];
int ans=INF;
int r,c;
void get_ans()
{
    for(int i=0;i<r;i++)
        for(int j=0;j<c;j++)
    {
        if(i==0||j==0||i==r-1||j==c-1 && maze[i][j])
        {
            if(cost_by_F[i][j] > cost_by_J[i][j])
            {
                if(cost_by_J[i][j]<ans)
                    ans=cost_by_J[i][j];
            }
        }
    }
}
void bfs(int x,int y,int cost[][1005],int choice)
{
	// 1是J
	// 2是F
    for(int i=0;i<r;i++)
        for(int j=0;j<c;j++)
    {
        cost[i][j] =INF;
        visit[i][j]=0;
    }
    queue<pair<int,int> > q;
    // J
    if(choice==1)
    {
        q.push(pair<int,int>(x,y));
        visit[x][y]=1;
        cost[x][y]=1;
    }
    // F
    else{
        for(int i=0;i<r;i++)
            for(int j=0;j<c;j++)
        {
            if(maze[i][j]==2)
            {
                q.push(pair<int,int>(i,j));
                visit[i][j]=1;
                cost[i][j]=1;
            }
        }
    }
    while(!q.empty())
    {
        pair<int,int> t = q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int x=t.first,y=t.second;
            x+=step[i][0],y+=step[i][1];
            if(x>=0&&x<r&&y>=0&&y>=0&&y<c&&!visit[x][y]&&maze[x][y])
            {
                visit[x][y]=1;
                cost[x][y]=cost[t.first][t.second]+1;
                q.push(pair<int,int> (x,y));
            }
        }
    }
}
int main()
{
    int n;
    cin>>n;
    for(int k=1;k<=n;k++)
    {
        cin>>r>>c;
        int x,y;
        for(int i=0;i<r;i++)
        {
            string s;
            cin>>s;
            for(int j=0;j<c;j++)
            {
                if(s[j]=='#') maze[i][j]=0;
                else if(s[j]=='.') maze[i][j]=1;
                else if(s[j]=='F') maze[i][j]=2;
                else
                {
                    maze[i][j]=1;
                    x=i,y=j;
                }
            }
        }
        bfs(x,y,cost_by_J,1);
        bfs(x,y,cost_by_F,2);
        get_ans();
        if(ans!=INF)
            cout<<ans<<endl;
        else
            cout<<"IMPOSSIBLE"<<endl;
        ans=INF;
    }
}

反思:

  1. 建圖可以不按照原來的符號,用自己定義的數字。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章