POJ 2111

记忆化搜索即可,设DP[I][J]为可到达的最大步数。

输出时用了一种较笨拙的方法,还有一种方法是使用最长上升子序列的方式,挺好,先排序,这让我想起上次BESTCODER的一题

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;
const int N=370;
struct {
	int x,y;
}que[N*N],dir[8];
int num[N][N];
int dp[N][N];
int n,tf,f,l;

bool ok(int x,int y,int i,int j){
	if(x>=1&&x<=n&&y>=1&&y<=n){
		if(num[x][y]>num[i][j])
		return true;
	}
	return false;
}

void dfs(int i,int j){
	int tx,ty;
	if(dp[i][j]!=-1) return ;
	dp[i][j]=1;
	for(int k=0;k<8;k++){
		tx=i+dir[k].x;
		ty=j+dir[k].y;
		if(ok(tx,ty,i,j)){
			dfs(tx,ty);
			if(dp[i][j]==-1||dp[tx][ty]+1>dp[i][j])
			dp[i][j]=dp[tx][ty]+1;
		}
	}
}

int main(){
	dir[0].x=2,dir[0].y=1;dir[1].x=2,dir[1].y=-1;
	dir[2].x=-2,dir[2].y=1;dir[3].x=-2,dir[3].y=-1;
	dir[4].x=1,dir[4].y=2; dir[5].x=-1;dir[5].y=2;
	dir[6].x=1,dir[6].y=-2;dir[7].x=-1,dir[7].y=-2;
	while(scanf("%d",&n)!=EOF){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				scanf("%d",&num[i][j]);
				dp[i][j]=-1;
			}
		}
		f=l=0;
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(dp[i][j]==-1){
					dfs(i,j);
					if(f==l){
						que[l].x=i,que[l].y=j;
						l++;
					}
					else if(dp[i][j]>dp[que[l-1].x][que[l-1].y]||(dp[i][j]==dp[que[l-1].x][que[l-1].y]&&num[i][j]<num[que[l-1].x][que[l-1].y])){
						l=f;
						que[l].x=i,que[l].y=j;
						l++;
					}
					else if(dp[i][j]==dp[que[l-1].x][que[l-1].y]&&num[i][j]==num[que[l-1].x][que[l-1].y]){
						que[l].x=i,que[l].y=j;
						l++;
					}
				}
			}
		}
		printf("%d\n",dp[que[f].x][que[f].y]);
		tf=f;f=l;
		int tx,ty,x,y;
		while(tf<f){
			if(f==l){
				printf("%d\n",num[que[tf].x][que[tf].y]);
			}
			x=que[tf].x; y=que[tf].y;
			for(int i=0;i<=8;i++){
				tx=x+dir[i].x;
				ty=y+dir[i].y;
				if(ok(tx,ty,x,y)){
					if(dp[tx][ty]+1==dp[x][y]){
						if(f==l){
							que[l].x=tx,que[l].y=ty;
							l++;
						}
						else if(dp[tx][ty]>dp[que[l-1].x][que[l-1].y]||(dp[tx][ty]==dp[que[l-1].x][que[l-1].y]&&num[tx][ty]<num[que[l-1].x][que[l-1].y])){
							l=f;
							que[l].x=tx,que[l].y=ty;
							l++;
						}
						else if(dp[tx][ty]==dp[que[l-1].x][que[l-1].y]&&num[tx][ty]==num[que[l-1].x][que[l-1].y]){
							que[l].x=tx,que[l].y=ty;
							l++;
						}
					}
				}
			}
			tf++;
			if(tf==f){
				tf=f; f=l;
			}
		}
	}
	return 0;
}

  

时间: 2024-11-04 14:17:31

POJ 2111的相关文章

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 se

POJ 2442 Sequence【堆】

题目链接:http://poj.org/problem?id=2442 题目大意:给出一个m*n的矩阵,从每一行中取出一个数相加,能得到n^m个不同的结果,要求输出其中前n项. 建立一个以n元数组为底层数组的堆,在这里,利用stl中的make_heap,pop_heap,push_heap等函数解决. 1.将第一组数据输入arr1数组,升序排序. 2.将接下来的数据输入到arr2数组中,并且heap[i]=arr1[0]+arr2[0...n-1],make_heap(heap,heap+n).

POJ 2411 Mondriaan&#39;s Dream(状压DP)

http://poj.org/problem?id=2411 求一个n*m矩阵用1*2方块去填满的情况有几种 思路:状压dp,先预处理那些状态之间能互相到达,情况就几种,上一个两个1,下一个状态也两个1,上一个为0,下一个必须为1,还有一种是上一个为1,下一个为0的情况 然后就一层层往后递推即可 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int

POJ - 3186 Treats for the Cows (区间DP)

题目链接:http://poj.org/problem?id=3186 题意:给定一组序列,取n次,每次可以取序列最前面的数或最后面的数,第n次出来就乘n,然后求和的最大值. 题解:用dp[i][j]表示i~j区间和的最大值,然后根据这个状态可以从删前和删后转移过来,推出状态转移方程: dp[i][j]=max(dp[i+1][j]+value[i]*k,dp[i][j-1]+value[j]*k) 1 #include <iostream> 2 #include <algorithm&

POJ 2533 - Longest Ordered Subsequence(最长上升子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=2533 Description A numeric sequence of ai is ordered if a1 < a2 < ... < aN. Let the subsequence of the given numeric sequence (a1, a2, ..., aN) be any sequence (ai1, ai2, ..., aiK)

POJ——T2271 Guardian of Decency

http://poj.org/problem?id=2771 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5932   Accepted: 2463 Description Frank N. Stein is a very conservative high-school teacher. He wants to take some of his students on an excursion, but he is

POJ——T2446 Chessboard

http://poj.org/problem?id=2446 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18560   Accepted: 5857 Description Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of c

poj 1088 滑雪 DP(dfs的记忆化搜索)

题目地址:http://poj.org/problem?id=1088 题目大意:给你一个m*n的矩阵 如果其中一个点高于另一个点 那么就可以从高点向下滑 直到没有可以下滑的时候 就得到一条下滑路径 求最大的下滑路径 分析:因为只能从高峰滑到低峰,无后效性,所以每个点都可以找到自己的最长下滑距离(只与自己高度有关).记忆每个点的最长下滑距离,当有另一个点的下滑路径遇到这个点的时候,直接加上这个点的最长下滑距离. dp递推式是,dp[x][y] = max(dp[x][y],dp[x+1][y]+

POJ 1385 计算几何 多边形重心

链接: http://poj.org/problem?id=1385 题意: 给你一个多边形,求它的重心 题解: 模板题,但是不知道为啥我的结果输出的确是-0.00 -0.00 所以我又写了个 if (ans.x == 0) ans.x = 0 感觉好傻逼 代码: 1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <queue> 5 #include <stack> 6