1. 程式人生 > >DFS和BFS 解棋盤遊戲(九度OJ 1091)

DFS和BFS 解棋盤遊戲(九度OJ 1091)

DFS利用遞迴,不必使用多餘的資料結構,實現簡單。但要注意剪枝。

BFS藉助佇列,往往在求最優解時使用。總是能找到最優解,某些情況下也要剪枝。

這兩種方法根據具體問題來使用。

以此題為例,DFS和BFS都可求解。

由於是求最優解,用BFS更為直接。

由於此題的不確定性,必須要考慮所有可能情況,結合剪枝。

題目1091:棋盤遊戲

時間限制:1 秒

記憶體限制:32 兆

特殊判題:

提交:616

解決:151

題目描述:

有一個6*6的棋盤,每個棋盤上都有一個數值,現在又一個起始位置和終止位置,請找出一個從起始位置到終止位置代價最小的路徑:
1、只能沿上下左右四個方向移動
2、總代價是沒走一步的代價之和
3、每步(從a,b到c,d)的代價是c,d上的值與其在a,b上的狀態的乘積
4、初始狀態為1

每走一步,狀態按如下公式變化:(走這步的代價%4)+1。

輸入:

第一行有一個正整數n,表示有n組資料。
每組資料一開始為6*6的矩陣,矩陣的值為大於等於1小於等於10的值,然後四個整數表示起始座標和終止座標。

輸出:

輸出最小代價。

樣例輸入:
1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
0 0 5 5
樣例輸出:
23

BFS程式碼:

#include <iostream>
#include <queue>
using namespace std;

struct Node
{
	int x, y, sum, statu;
};

int ans;
int map[6][6];
int opt[6][6][4]; //記錄最優解,剪枝條件。4中狀態都要記錄
Node start;
int ex, ey;
int cnt = 0;
int dir[4][2] = {{ 0, 1 },{ 1, 0 },{ 0, -1 },{ -1, 0 } };
queue<Node> q;
void bfs(Node n)
{
	q.push(n);
	int tempx, tempy, cost;
	while (!q.empty())
	{
		cnt++;
		Node tn = q.front();
		q.pop();
		for (int i = 0; i < 4; i++)
		{
			tempx = tn.x + dir[i][0];
			tempy = tn.y + dir[i][1];
			if (tempx >= 0 && tempx < 6 && tempy >= 0 && tempy < 6)
			{
				cost = tn.statu * map[tempx][tempy];
				//如果這一步比以前的某一步代價還大  或者 比到終點的代價還大
				if (tn.sum + cost < opt[tempx][tempy][cost % 4 ] && tn.sum + cost < opt[ex][ey][cost % 4 ])
				{
					opt[tempx][tempy][cost % 4] = tn.sum + cost;
					Node temp;
					temp.x = tempx;
					temp.y = tempy;
					temp.sum = tn.sum + cost;
					temp.statu = cost % 4 + 1;
					q.push(temp);
				}
			}
		}
	}

}

int main()
{
	int k;
	cin >> k;
	while (k--)
	{
		for (int i = 0; i < 6; i++)
			for (int j = 0; j < 6; j++)
			{
				cin >> map[i][j];
				for(int k=0; k<4; k++)
					opt[i][j][k] = 100000;
			}
		start.sum = 0;
		start.statu = 1;
		ans = 100000;
		cin >> start.x >> start.y >> ex >> ey;
		bfs(start);
		for (int i = 0; i < 4; i++)
		{
			if (ans > opt[ex][ey][i])
				ans = opt[ex][ey][i];
		}
		//cout << cnt << endl;
		cout << ans << endl;
	}
	return 0;
}

Language: C++ Result: Accepted Time:10 ms Memory:1516 kb

DFS程式碼;

#include <iostream>
using namespace std;
int map[6][6];
int sx,sy,ex,ey,ans;
int cnt = 0;
int dir[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
bool visit[6][6];
void dfs(int x,int y,int sum,int statu){
    cnt ++;
    if(sum < ans){
        if(x == ex && y == ey){
                 ans = sum;
                return;
        }
        for(int i=0; i<4; i++){
            int tempx = x + dir[i][0];
            int tempy = y + dir[i][1];
            if(visit[tempx][tempy] && tempx >=0 && tempx < 6 && tempy >=0 && tempy < 6){
                int cost = statu * map[tempx][tempy];
                visit[tempx][tempy] = false;
                dfs(tempx, tempy, sum+cost, cost % 4 + 1);
                visit[tempx][tempy] = true;
            }
        }
    }
}

int main() {
    int k;
    cin >> k;
    while(k--){
        for(int i=0; i<6; i++)
            for(int j=0; j<6; j++){
                 cin >> map[i][j];
                 visit[i][j] = true;
            }
        cin >> sx >> sy >> ex >> ey;
        ans = 1000000;
        dfs(sx,sy,0,1);
        //cout  << cnt << endl;
        cout << ans << endl;
    }
    return 0;
}

Language: C++ Result: Accepted Time:10 ms Memory:1512 kb