秋招每日一题T12——立方体Ⅳ

题目描述

Vincenzo 决定制作立方体 IV,但所有预算只够制作一个正方形迷宫。

它是一个完美的迷宫,每个房间都呈正方形,并具有 4 扇门(四个边一边 1 个)。

每个房间里都有一个号码。

一个人只有在下一个房间的号码比当前房间的号码大 1 的情况下,才能从当前房间移动到下一个房间。

现在,Vincenzo 为所有房间分配了唯一的号码(1,2,3,…S2)然后将 S2 个人放在了迷宫中,每个房间 1 个,其中 S 是迷宫的边长。

能够移动次数最多的人将获胜。

弄清楚谁将成为赢家,以及他将能够到达的房间数量。

输入格式
第一行包含整数 T,表示共有 T 组测试数据。

每组测试数据第一行包含整数 S,表示迷宫的边长。

接下来 S 行,每行包含 S 个整数,表示具体的迷宫的房间号分布,需注意 1,2,3,…S2 这 S2 个数字,每个数字只出现一次。

输出格式
每组数据输出一个结果,每个结果占一行。

结果表示为 Case #x: r d,其中 x 是组别编号(从 1 开始),r 是获胜的人最初所在房间的房间号,d 是他可以到达的房间数量。

如果有多个人可到达的房间数相同,那么最初所在房间的房间号最小的人将获胜。

数据范围
1≤T≤100,
1≤S≤1000

在这里插入图片描述

思路

①一开始就想到这道题的数据量会很大,想用搜索来做,但是看了眼闫老师的代码,发现可以用记忆化搜索进行优化。
②记忆化搜索,即搜索过的位置直接返回其值,没搜索过的位置进行搜索。因此在输入矩阵之后,从第一个点开搜,它可以去上、下、左、右,如果找到符合题意的下一个位置,就记录一下当前这个点可以走的最大值。

代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1005;
int a[maxn][maxn] = {0};
int f[maxn][maxn] = {0};
int s,t;
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
int dp(int x,int y){
	int& v = f[x][y];	#v为f[x][y]的引用。
	if(v != -1)	return v;	#如果已经被搜过,则直接返回之前搜过的值。
	v = 1;				#否则初始化为1,因为它再不济也可以走自己(不动)。防止反复搜索。
	for(int i=0;i<4;i++){
		int nx = x + dx[i];
		int ny = y + dy[i];
		if(nx > 0 && ny > 0 && nx <= s && ny <= s && a[nx][ny] == a[x][y] + 1){
			v = max(v, dp(nx,ny) + 1);
			#动规思想,(nx,ny)(x,y)下一个可以去的点,由贪心思想,(x,y)能到的房间
			#数量一定比它下一个可以到的点(nx,ny)大,因此还需要搜索下一个位置(nx,ny)
			#可以到达的房间数((nx,ny)最少是1,故(x,y)最小变成了2)。
		}
	}
	return v;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>t;
	for(int cases = 1;cases <= t; cases ++){
		cin>>s;
		memset(f,-1,sizeof(f));	#每组数据都需要对f初始化
		for(int i=1;i<=s;i++){
			for(int j=1;j<=s;j++){
				cin>>a[i][j];
			}
		}
		int id,cnt = 0;
		for(int i=1;i<=s;i++){
			for(int j=1;j<=s;j++){
				int t = dp(i,j);	#从第一给点开始遍历
				if(t > cnt || t == cnt && id > a[i][j]){
					id = a[i][j];
					cnt = t;
				}
			}
		}
		cout<<"Case #"<<cases<<": "<<id<<' '<<cnt<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值