九度[1091]-棋盘游戏

九度[1091]-棋盘游戏

题目描述:
有一个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和DFS都可以,就是需要注意剪枝,否则搜索空间过大。

AC代码:

#include <cstdio>
#include <queue>
#define LEN 6
using namespace std;
int n;
int dat[LEN][LEN], opt[LEN][LEN][4];
int moveX[4] = {0, 1, 0, -1}, moveY[4] = {1, 0, -1, 0};

struct node{
    int x, y, value, cost;
}start, end;

bool isOK(node n, int type){
    if(n.x + moveX[type] >= 0 && n.x + moveX[type] <= LEN-1 && n.y + moveY[type] >= 0 && n.y + moveY[type] <= LEN-1) return true;
    else return false;
}

int findPath(node a, node b){
    int min = 1000000000;
    queue<node> que;
    que.push(a);
    node n;
    while(!que.empty()){
        n = que.front();
        que.pop();
        if(n.x == b.x && n.y == b.y) {
            if(n.cost < min) min = n.cost;
            continue;
        } 
        for(int i = 0; i < 4; i++){
            if(isOK(n, i)) {
                node tmp = {n.x+moveX[i], n.y+moveY[i]};
                int tmpCost = n.value * dat[tmp.x][tmp.y];
                tmp.value = tmpCost % 4 + 1;
                tmp.cost = n.cost + tmpCost;
                if(tmp.cost < opt[b.x][b.y][tmp.value-1] && tmp.cost < opt[tmp.x][tmp.y][tmp.value-1]) {
                    opt[tmp.x][tmp.y][tmp.value-1] = tmp.cost;
                    que.push(tmp);
                }   
            }
        }
    }
    return min;
}

int main(){
    freopen("C:\\Users\\Administrator\\Desktop\\test.txt", "r", stdin);
    while(scanf("%d", &n) != EOF){
        while(n--){
            for(int i = 0; i < LEN; i++){
                for(int j = 0; j < LEN; j++){
                    scanf("%d", &dat[i][j]);
                    for(int k = 0; k < 4; k++){
                        opt[i][j][k] = 1000000000;
                    }
                }
            }
            scanf("%d%d%d%d", &start.x, &start.y, &end.x, &end.y);
            start.value = 1;
            start.cost = 0;
            printf("%d\n", findPath(start, end));
        }

    }
    fclose(stdin);
    return 0;
}

参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值