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 }
原文地址:https://www.cnblogs.com/ljh2000-jump/p/5655345.html