fzu 2150 Fire Game
題目大意:
給出一個m*n的圖,‘#’表示草坪,‘ . ’表示空地,然後可以選擇在任意的兩個草坪格子點火,火每 1 s會向周圍四個格子擴散,問選擇那兩個點使得燃燒所有的草坪花費時間最小?
具體思路:
數據範圍較小,直接枚舉兩點選擇的任意情況,分別進行bfs。取最優解就行
詳細:
枚舉兩個人可能選的座標情況,作爲不同的初始狀態
對每個初始狀態進行bfs搜索,得到木板上的每塊草地被燒完的時間
其中燒完杯子耗時最久的時間就是總時間
然後根據此初始狀態的耗時去更新答案
得到所有初始狀態中耗時最小的時間
若無法更新得到,則輸出-1
具體代碼:
因爲fzu題目失效,所以代碼沒有測試過。
#include<iostream>
#include<queue>
#include<cstdio>
#include<string>
using namespace std;
const int INF = 1e5;
int step[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };
int board[11][11];
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)ans = res;
}
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));
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, y = t.second;
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(); //計算該狀態下的結果,更新答案
}
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;
}
}
//init(); //初始化所有狀態的最少時間
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++)
if (board[i][j] && board[p][q]) {
//cnt[i][j][p][q] = INF;
bfs(i, j, p, q);
}
if(ans!=INF)printf("case %d:%d\n", k, ans);
else printf("case %d:-1\n", k);
ans = INF;
}
return 0;
}