1. 程式人生 > >poj 2111 Millenium Leapcow(記憶化搜索)

poj 2111 Millenium Leapcow(記憶化搜索)

cto tor ssi can cti trie point ted spec

Description

The cows have revised their game of leapcow. They now play in the middle of a huge pasture upon which they have marked a grid that bears a remarkable resemblance to a chessboard of N rows and N columns (3 <= N <= 365).

Here‘s how they set up the board for the new leapcow game:

* First, the cows obtain N x N squares of paper. They write the integers from 1 through N x N, one number on each piece of paper.

* Second, the ‘number cow‘ places the papers on the N x N squares in an order of her choosing.

Each of the remaining cows then tries to maximize her score in the game.

* First, she chooses a starting square and notes its number.

* Then, she makes a ‘knight‘ move (like the knight on a chess board) to a square with a higher number. If she‘s particularly strong, she leaps to the that square; otherwise she walks.

* She continues to make ‘knight‘ moves to higher numbered squares until no more moves are possible.

Each square visited by the ‘knight‘ earns the competitor a single point. The cow with the most points wins the game.

Help the cows figure out the best possible way to play the game.

Input

* Line 1: A single integer: the size of the board

* Lines 2.. ...: These lines contain space-separated integers that tell the contents of the chessboard. The first set of lines (starting at the second line of the input file) represents the first row on the chessboard; the next set of lines represents the next row, and so on. To keep the input lines of reasonable length, when N > 15, a row is broken into successive lines of 15 numbers and a potentially shorter line to finish up a row. Each new row begins on its own line.

Output

* Line 1: A single integer that is the winning cow‘s score; call it W.

* Lines 2..W+1: Output, one per line, the integers that are the starting square, the next square the winning cow visits, and so on through the last square. If a winning cow can choose more than one path, show the path that would be the ‘smallest‘ if the paths were sorted by comparing their respective ‘square numbers‘.

Sample Input

4
1 3 2 16
4 10 6 7
8 11 5 12
9 13 14 15

Sample Output

7
2
4
5
9
10
12
13

題意:給你一個矩陣,問你按照象棋馬的走法,下一步比上一步的數大,問長度最長的序列是多長,然後輸出序列。如果有多個最長序列輸出字典序最小的那個。
這是看到的一個代碼:
技術分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <queue>
 5 #include <vector>
 6 #include <algorithm>
 7 #include <map>
 8 using namespace std;
 9 typedef pair<int,int>P;
10 const double eps=1e-9;
11 const int maxn=200100;
12 const int mod=1e9+7;
13 const int INF=1e9;
14 int M[370][370],dp[370][370];
15 int N;
16 int dx[8]= {1,1,2,2,-1,-1,-2,-2};
17 int dy[8]= {2,-2,1,-1,2,-2,1,-1};
18 P path[370][370];
19 vector<P>res;
20 int DP(int x,int y)
21 {
22     int &m=dp[x][y];
23     if(m) return m;
24     m=1;
25     for(int i=0; i<8; i++)
26     {
27         int nx=x+dx[i];
28         int ny=y+dy[i];
29         if(1<=nx&&nx<=N&&1<=ny&&ny<=N&&M[nx][ny]>M[x][y])
30         {
31             if(m<DP(nx,ny)+1)
32             {
33                 m=DP(nx,ny)+1;
34                 path[x][y]=make_pair(nx,ny);
35             }
36             else if(DP(nx,ny)+1==m)
37             {
38                 if(M[path[x][y].first][path[x][y].second]>M[nx][ny])
39                 {
40                     path[x][y]=make_pair(nx,ny);
41                 }
42             }
43         }
44     }
45     return m;
46 }
47 int main()
48 {
49     while(~scanf("%d",&N))
50     {
51         for(int i=1; i<=N; i++)
52         {
53             for(int j=1; j<=N; j++)
54             {
55                 scanf("%d",&M[i][j]);
56             }
57         }
58         int MAX=1,cnt;
59         for(int i=1; i<=N; i++)
60         {
61             for(int j=1; j<=N; j++)
62             {
63                 cnt=DP(i,j);
64                 if(MAX<cnt)
65                 {
66                     MAX=cnt;
67                     res.clear();
68                     res.push_back(make_pair(i,j));
69                 }
70                 else if(MAX==cnt)
71                 {
72                     res.push_back(make_pair(i,j));
73                 }
74             }
75         }
76         int keyx,keyy,key;
77         key=INF;
78         for(int i=0; i<res.size(); i++)
79             if(M[res[i].first][res[i].second]<key)
80             {
81                 key=M[res[i].first][res[i].second];
82                 keyx=res[i].first;
83                 keyy=res[i].second;
84             }
85         printf("%d\n",MAX);
86         while(1)
87         {
88             printf("%d\n",M[keyx][keyy]);
89             int t=path[keyx][keyy].second;
90             keyx=path[keyx][keyy].first;
91             keyy=t;
92             if(!keyx)
93                 break;
94         }
95     }
96     return 0;
97 }
View Code

知識點:

這個代碼的主要想法是,如同最短路一樣,path中儲存的是當前節點的下一步應該走的位置,然後進行搜索直到遍歷了所有的點。

poj 2111 Millenium Leapcow(記憶化搜索)