• 九度oj 题目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

    做这个题需要用到深度优先搜索或广度优先搜索
    对于深度优先搜索而言,其基本思路是从起始点出发,遍历4个方向,一直走下去,直到终点。但要注意如何去剪枝。这里把花费作为参数传入到函数中,作为剪枝的条件。代码如下
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <string>
     5 #include <cmath>
     6 #include <algorithm>
     7 #define inf 0x3f3f3f3f
     8 
     9 int graph[6][6];
    10 int dir[4][2] = { {0,1},{1,0},{0,-1},{-1,0} }; 
    11 bool isVisit[6][6];
    12 
    13 int startx, starty, endx, endy;
    14 int ans;
    15 
    16 void dfs(int nowx, int nowy, int state, int sum) {
    17     if(sum > ans) {
    18         return;
    19     }
    20     if(nowx == endx && nowy == endy) {
    21         ans = sum;
    22     }    
    23     for(int i = 0; i < 4; i++) {
    24         int tempx = nowx + dir[i][0];
    25         int tempy = nowy + dir[i][1];
    26         if(tempx >= 0 && tempx <= 5 && tempy >= 0 && tempy <= 5 && isVisit[tempx][tempy] == false) {
    27             int cost = state * graph[tempx][tempy];
    28             int stateNext = (cost%4) + 1;
    29             isVisit[tempx][tempy] = true;
    30             dfs(tempx, tempy, stateNext, sum + cost);
    31             isVisit[tempx][tempy] = false;
    32         }
    33         
    34     }
    35 }
    36 
    37 int main(int argc, char const *argv[])
    38 {
    39     
    40      int n;
    41      //freopen("input.txt","r",stdin);
    42      scanf("%d",&n);
    43      while(n--) {
    44         for(int i = 0; i < 6; i++) {
    45             for(int j = 0; j < 6; j++) {
    46                 scanf("%d",&graph[i][j]);
    47                 isVisit[i][j] = false;
    48             }
    49         }
    50         scanf("%d %d %d %d",&startx, &starty, &endx, &endy);    
    51         ans = inf;
    52         dfs(startx, starty,1,0);
    53         printf("%d
    ", ans);
    54      }
    55 
    56     return 0;
    57 }

    对于广度优先搜索,需要一个队列将每一层可以到达的点加入到队列中,每一个个点最多只有4种状态。我们用一个数组存这四种状态中每一种状态的最小代价,遍历到终点时四种代价之中的最小者则为最小花费

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <string>
     5 #include <cmath>
     6 #include <algorithm>
     7 #include <queue>
     8 #define inf 0x3f3f3f3f
     9 using namespace std;
    10 
    11 int graph[6][6];
    12 int dir[4][2] = { {0,1},{1,0},{0,-1},{-1,0} }; 
    13 int opt[6][6][5];
    14 
    15 int startx, starty, endx, endy;
    16 int ans;
    17 
    18 struct Node
    19 {
    20     int x;
    21     int y;
    22     int state;
    23     int cost;
    24 };
    25 
    26 queue <Node> Q;
    27 
    28 void bfs(Node start) {
    29     Q.push(start);
    30 
    31     int tempx, tempy, cost;
    32     while(!Q.empty()) {
    33         Node now = Q.front();
    34         Q.pop();
    35         for(int i = 0; i < 4; i++) {
    36             tempx = now.x + dir[i][0];
    37             tempy = now.y + dir[i][1];
    38             if(tempx >= 0 && tempx <= 5 && tempy >= 0 && tempy <= 5) {
    39                 cost = now.state * graph[tempx][tempy];
    40                 int nextState = cost % 4 +1;
    41                 if(now.cost + cost < opt[tempx][tempy][nextState] && now.cost + cost < opt[endx][endy][nextState]) {
    42                     opt[tempx][tempy][nextState] = now.cost + cost;
    43                     Node add;
    44                     add.x = tempx;
    45                     add.y = tempy;
    46                     add.state = nextState;
    47                     add.cost = now.cost + cost;
    48                    // printf("%d %d %d
    ",tempx, tempy, add.cost);
    49                     Q.push(add);
    50                 }
    51             }
    52         }
    53     }
    54 }
    55 
    56 int main(int argc, char const *argv[])
    57 {
    58     
    59      int n;
    60      freopen("input.txt","r",stdin);
    61      //freopen("output.txt","w",stdout);
    62      scanf("%d",&n);
    63      while(n--) {
    64         for(int i = 0; i < 6; i++) {
    65             for(int j = 0; j < 6; j++) {
    66                 scanf("%d",&graph[i][j]);
    67                 for(int k = 1; k <= 4; k++) {
    68                     opt[i][j][k] = inf;
    69                 }
    70             }
    71         }
    72         scanf("%d %d %d %d",&startx, &starty, &endx, &endy);    
    73         ans = inf;
    74         Node start;
    75         start.x = startx, start.y = starty,start.state = 1, start.cost = 0;
    76         bfs(start);
    77         int min = inf;
    78         for(int i = 1; i <= 4; i++) {
    79             if(min > opt[endx][endy][i]) {
    80                 min = opt[endx][endy][i];
    81             }
    82         }
    83         printf("%d
    ", min);
    84      }
    85 
    86     return 0;
    87 }
  • 相关阅读:
    APP之百度地图SDK的AK值获取(android)
    横向滚动菜单-选中标题居中显示
    函数按引用传参问题
    js验证提交
    Java servlet ajax
    数据库3种读
    mybatis插件
    mybatis 缓存
    从前端对象中获取的文本变为字符串,并替换其中一些指定的字符
    多个窗口开启后,切换到指定title的窗口
  • 原文地址:https://www.cnblogs.com/jasonJie/p/5694170.html
Copyright © 2020-2023  润新知