poj 2111 Millenium Leapcow(记忆化搜索)

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中储存的是当前节点的下一步应该走的位置,然后进行搜索直到遍历了所有的点。

 

posted @ 2017-05-23 16:42  Wally的博客  阅读(237)  评论(0编辑  收藏  举报