题目1091:棋盘游戏 -- DFS BFS

题目1091:棋盘游戏
时间限制:1 秒内存限制:32 兆特殊判题:否提交:1469解决:394
题目描述:
有一个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
来源:
2005年上海交通大学计算机研究生机试真题
答疑:
解题遇到问题?分享解题心得?讨论本题请访问:http://t.jobdu.com/thread-7814-1-1.html

*这题开始用动态规划会发现不可行,必须用搜索,DFS ,BFS 都需要优化
虽然参考网上的AC了这题, 九度论坛上出题也比较坑。这题本身非常好,作为DFS , BFS 练习 很经典,可以敲上n遍了 。 注意BFS利用 queue,DFS 注意回溯。*
DFS

#include <stdio.h>
#include <iostream>
using namespace std;

int ans;
int map[6][6];
int stax , stay ,ex, ey;
int dir[4][2] ={ { 0, 1 }, { 1, 0 },{ 0, -1 }, { -1, 0 } };
bool vis[6][6];

void dfs(int x , int  y  , int sum , int statu)
{
    if(sum < ans)
    {
        if(x == ex && y == ey)
        {
            ans = sum ;
            return ;
        }else{
            for (int i = 0; i < 4; i++) // 四个方向
            {
                int tempx = x + dir[i][0];
                int tempy = y + dir[i][1];
                if ( !vis[tempx][tempy] && tempx >= 0 && tempx < 6 && tempy >= 0 && tempy < 6)
                {
                    int cost = statu * map[tempx][tempy]; // // 每步(从a,b到c,d)的代价是c,d上的值与其在a,b上的状态的乘积
                    int sum2 = sum + cost; // 走到下一步的总和
                    int statu2 = cost % 4 + 1; // 状态按如下公式变化:(走这步的代价%4)+1。
                    vis[tempx][tempy] = true ; 
                    dfs(tempx , tempy , sum2 , statu2);
                    vis[tempx][tempy] = false ; // 回溯
                }
            }
        }
    }
}
int main()
{
    //freopen("in.txt","r",stdin);
    int k;
    cin >> k;
    while (k--)
    {
        for (int i = 0; i < 6; i++)
        { 
            for (int j = 0; j < 6; j++)
            {
                cin >> map[i][j];
                vis[i][j] = false;
            }
        }
        ans = 999999999;
        cin >> stax >> stay >> ex >> ey; // 起点 终点
        //vis[stax][stay] = true; // 这里必须注释   是可以回到起点吗
        dfs(stax , stay , 0 , 1);
        printf("%d\n",ans);
    }
    return 0;
}

BFS

#include <stdio.h>
#include <iostream>
#include <queue>
using namespace std;
class Node
{
public:
    int x, y, sum, statu;
};
int ans;
int map[6][6];
int opt[6][6][5]; //记录最优解,剪枝条件
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();
        //opt[tn.x][tn.y] = tn.sum ;
        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) //坐标必须合理
            {
                // 每步(从a,b到c,d)的代价是c,d上的值与其在a,b上的状态的乘积
                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; // 状态按如下公式变化:(走这步的代价%4)+1。
                    q.push(temp); // 入队列
                }
            }
        }
    }
}

int main()
{
    //freopen("in.txt","r",stdin);
    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; // 起点的总代价为 0 
        start.statu = 1; // 起点的状态为 1
        ans = 100000;
        cin >> start.x >> start.y >> ex >> ey; // 起点 终点
        bfs(start); // bfs
        for (int i = 0; i < 4; i++) // 代价最小的就是最优解
        {
            if (ans > opt[ex][ey][i])
                ans = opt[ex][ey][i];
        }
        cout << ans << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值