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 }

知识点:

这个代码的主要想法是,如同最短路一样,path中储存的是当前节点的下一步应该走的位置,然后进行搜索直到遍历了所有的点。

时间: 2024-10-28 19:57:38

poj 2111 Millenium Leapcow(记忆化搜索)的相关文章

poj 1088 滑雪 【记忆化搜索】+【DFS】

策略:如题 题目链接:http://poj.org/problem?id=1088 代码: #include<stdio.h> #include<string.h> int map[105][105], dp[105][105], n, m; const int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0}; //四个方向 int limit(int x, int y) //判断是不是越界了 { if(x<1||x>n||y<1||

poj 1695 Magazine Delivery 记忆化搜索

dp[a][b][c],表示三个人从小到大依次在a,b,c位置时,距离结束最少的时间. 每次选一个人走到c+1位置搜索就好了. 坑点在于不能floyd,估计题目没说清楚,意思就是如果没送Li,那么Li~n的点连去都不能去. #include<cstdio> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define INF 0x3f3f3f3f int

POJ 2738 Two Ends 记忆化搜索

题意比较简单,两个人拿偶数张卡片,要么拿当前的最左边,要么拿最右边,尽量拿大的,拿完后求第一个人拿的卡片数字总和减去第二个人卡片的数字总和,求最大差值. 刚开始写记忆化搜索,参考了一下别人的代码,但是还有一个地方不太明白,就是当第一个人拿右边的时候,为什么写成num[x]<=num[y-1]会wa(⊙o⊙)- 求指教额... #include <iostream> #include<stdio.h> #include<algorithm> #include<

POJ 1088 滑雪(记忆化搜索)

滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 92384   Accepted: 34948 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17

POJ 3176-Cow Bowling(DP||记忆化搜索)

Cow Bowling Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14210   Accepted: 9432 Description The cows don't use actual bowling balls when they go bowling. They each take a number (in the range 0..99), though, and line up in a standard

[ACM] POJ 1088 滑雪 (记忆化搜索复习)

滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 77763   Accepted: 28905 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17

poj 1088 滑雪【记忆化搜索】

题目链接:http://poj.org/problem?id=1088 基础题,不讲了,饿了 吃早饭去... 代码: #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <math.h> #include <map> #include <string>

POJ 2704 Pascal&#39;s Travels (基础记忆化搜索)

Pascal's Travels Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5328   Accepted: 2396 Description An n x n game board is populated with integers, one nonnegative integer per square. The goal is to travel along any legitimate path from t

POJ 1351 Number of Locks (记忆化搜索 状态压缩)

Number of Locks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1161   Accepted: 571 Description In certain factory a kind of spring locks is manufactured. There are n slots (1 < n < 17, n is a natural number.) for each lock. The height