• codevs1358 棋盘游戏


    题目描述 Description

    这个游戏在一个有10*10个格子的棋盘上进行,初始时棋子位于左上角,终点为右下角,棋盘上每个格子内有一个0到9的数字,每次棋子可以往右方或下方的相邻格子移动,求一条经过数字之和最小且经过0到9的所有数字的合法路径,输出其长度。(经过的数字包括左上角和右下角)

    输入描述 Input Description

    输入包含10行,每行10个数字,以空格隔开,表示棋盘格子上的权值。数据保证存在合法路径。

    输出描述 Output Description

    输出所求路径的权值和。

    样例输入 Sample Input

    0 1 2 3 4 5 6 7 8 9

    1 1 1 1 1 1 1 1 1 0

    2 1 1 1 1 1 1 1 1 0

    3 1 1 1 1 1 1 1 1 0

    4 1 1 1 1 1 1 1 1 0

    5 1 1 1 1 1 1 1 1 0

    6 1 1 1 1 1 1 1 1 0

    7 1 1 1 1 1 1 1 1 0

    8 1 1 1 1 1 1 1 1 0

    9 1 1 1 1 1 1 1 1 5

    样例输出 Sample Output

    50

    样例解释

    先一直向右走到第一行末尾,再竖直向下走位最优路径。

    正解:状压DP

    解题报告:

      最近没事做,刷点状压DP水题。

      f[i][j][s]记录到达(i,j)时状态为s的最优答案,显然可以吧0到9是否走过压成二进制。复杂度正确。

      转移的时候注意一下状态这一维度要在最内层,开始样例都没过,才发现状态必须在最里层。。。

     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #ifdef WIN32   
    14 #define OT "%I64d"
    15 #else
    16 #define OT "%lld"
    17 #endif
    18 using namespace std;
    19 typedef long long LL;
    20 const int MAXN = 12;
    21 const int MAXS = (1<<12);
    22 int n;
    23 int a[MAXN][MAXN];
    24 int f[MAXN][MAXN][MAXS];
    25 
    26 inline int getint()
    27 {
    28        int w=0,q=0;
    29        char c=getchar();
    30        while((c<'0' || c>'9') && c!='-') c=getchar();
    31        if (c=='-')  q=1, c=getchar();
    32        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
    33        return q ? -w : w;
    34 }
    35 
    36 inline void solve(){
    37     n=10; memset(f,127/3,sizeof(f));
    38     for(int i=1;i<=n;i++)
    39     for(int j=1;j<=n;j++)
    40         a[i][j]=getint();
    41     int end=(1<<n)-1;
    42     f[1][1][1<<a[1][1]]=a[1][1];
    43     //不能置为0!!!!!!只能从1出发
    44 
    45     //for(int i=1;i<=n;i++)
    46     //    for(int j=1;j<=n;j++)
    47     //        f[i][j][0]=0;
    48        
    49     for(int j=1;j<=n;j++)
    50     for(int k=1;k<=n;k++)  {
    51         if(j==1 && k==1) continue;
    52         for(int i=1;i<=end;i++) {
    53         if((1<<a[j][k] | i )!=i) continue;        
    54         int lin=(1<<30);
    55         lin=min(f[j-1][k][i],f[j][k-1][i]);
    56         lin=min(lin,min(f[j-1][k][i-(1<<a[j][k])],f[j][k-1][i-(1<<a[j][k])]));
    57         f[j][k][i]=lin+a[j][k];
    58         }
    59     }
    60     printf("%d",f[n][n][end]);
    61 }
    62 
    63 int main()
    64 {
    65   solve();
    66   return 0;
    67 }
  • 相关阅读:
    三次请求(读-改-读)引出nibernate 一级缓存
    算法竞赛入门经典第一、二章摘记
    uva 10905 Children's Game
    uva 11205 The broken pedometer
    uva 10160 Servicing stations
    uva 208 Firetruck
    uva 167 The Sultan's Successors
    zoj 1016 Parencodings
    uva 307 Sticks
    uva 216 Getting in Line
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5655345.html
Copyright © 2020-2023  润新知