牛客网-棋盘游戏【bfs】

有一个6*6的棋盘,每个棋盘上都有一个数值,现在又一个起始位置和终止位置,请找出一个从起始位置到终止位置代价最小的路径: 1、只能沿上下左右四个方向移动 2、总代价是没走一步的代价之和 3、每步(从a,b到c,d)的代价是c,d上的值与其在a,b上的状态的乘积 4、初始状态为1 每走一步,状态按如下公式变化:(走这步的代价%4)+1。

  • 输入描述:

    每组数据一开始为6*6的矩阵,矩阵的值为大于等于1小于等于10的值,然后四个整数表示起始坐标和终止坐标。

  • 输出描述:

    输出最小代价


果然NK就可以为所欲为,感觉dfs太耗时可能过不了,结果也是过了,ԾㅂԾ,,这道题的代价有点启发式,导致虽然知道始末位置但是不能双向bfs。这个启发式的思想导致了使用最短路的算法特别是迪杰斯特拉容易陷入误区,因为最短路算法是按照路径最短来向外扩展的,但是这道题里有着状态的限制,贪心的选择当前路径最短的值有可能使得结果不是最优。所以还是怪怪的枚举状态吧

先放一个spfa WA的代码“


ll m[MAX][MAX], vis[MAX][MAX], dist[MAX][MAX], state[MAX][MAX];
ll dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
ll sx, sy, tx, ty;
 
struct P {
    ll x, y;
    P(ll xx = 0, ll yy = 0) { x = xx, y = yy; }
};
 
bool check(ll x, ll y) {
    if (x < 6 && x >= 0 && y < 6 && y >= 0)return true;
    return false;
}
 
ll bfs() {
    for (int i = 0; i < 6; i++)for (int j = 0; j < 6; j++)dist[i][j] = inf;
    queue<P>q;
    q.push(P(sx, sy)); vis[sx][sy] = 1; dist[sx][sy] = 0; state[sx][sy] = 1;
    while (!q.empty()) {
        P t = q.front(); q.pop(); vis[t.x][t.y] = 0;
        if (t.x == tx && t.y == ty)continue;
        for (int i = 0; i < 4; i++) {
            ll xx = t.x + dx[i], yy = t.y + dy[i];
            if (check(xx, yy) && dist[xx][yy] > dist[t.x][t.y] + m[xx][yy] * state[t.x][t.y]) {
                dist[xx][yy] = dist[t.x][t.y] + m[xx][yy] * state[t.x][t.y];
                state[xx][yy] = (m[xx][yy] * state[t.x][t.y]) % 4 + 1;
                if (!vis[xx][yy]) {
                    q.push(P(xx, yy)); vis[xx][yy] = 1;
                }
            }
        }
    }
    return dist[tx][ty];
}
 
int main() {
 
    for (int i = 0; i < 6; i++)for (int j = 0; j < 6; j++)cin >> m[i][j];
    cin >> sx >> sy >> tx >> ty;
    cout << bfs() << endl;
}

底下是AC的dfs

ll m[MAX][MAX], vis[MAX][MAX], res = inf;
ll dx[4] = { 0,0,1,-1 }, dy[4] = { 1,-1,0,0 };
ll sx, sy, tx, ty;

struct P {
	ll x, y;
	P(ll xx = 0, ll yy = 0) { x = xx, y = yy; }
};

bool check(ll x, ll y) { 
	if (x < 6 && x >= 0 && y < 6 && y >= 0 && !vis[x][y])return true; 
	return false;
}

void dfs(ll x, ll y, ll cost, ll state) {
	if (x == tx && y == ty) {
		if (cost < res)res = cost; return;
	}
	for (int i = 0; i < 4; i++) {
		ll xx = dx[i] + x, yy = dy[i] + y;
		if (check(xx, yy)) {
			vis[xx][yy] = 1;
			dfs(xx, yy, cost + state * m[xx][yy], state*m[xx][yy] % 4 + 1);
			vis[xx][yy] = 0;
		}
	}
	return;
}

int main() {
	for (int i = 0; i < 6; i++)for (int j = 0; j < 6; j++)cin >> m[i][j];
	cin >> sx >> sy >> tx >> ty;
	dfs(sx, sy, 0, 1);
	cout << res << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值