【vijos】1791 骑士的旅行(特殊的技巧)

https://vijos.org/p/1791

暴力的话只想到bfs,然后估计是状态超了才得20分。

噗,为啥暴力就不能想得简单点QAQ。。。。。这种思想很好啊。

这一题我看了题解后不得不说我竟然没想到。。

为啥要bfs。。这种找路径的依赖前边状态的不需要bfs啊!

因为bfs是无限拓展的,状态很大,本题又是8种决策,状态达到8^n啊。。。。sad。。

我们可以这样想,因为状态是向前走的,而且当前状态只依赖于前一个状态,那么我们可以用dp思想啊。。直接枚举当前状态然后看是否根据上一状态到达,标记即可。。

我实在太弱QAQ

(虽然这样做还是暴力,我也没能做出正解,但是这种思想值得写这篇blog,orz

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << ‘\t‘; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<‘0‘||c>‘9‘; c=getchar()) if(c==‘-‘) k=-1; for(; c>=‘0‘&&c<=‘9‘; c=getchar()) r=r*10+c-‘0‘; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; }

const int N=40, dx[]={-1, -2, -2, -1, 1, 2, 2, 1}, dy[]={-2, -1, 1, 2, 2, 1, -1, -2};
int vis[2][N][N], n, T, X, Y, cnt, a[N][N];
int main() {
	read(n); read(T); read(X); read(Y);
	for1(i, 1, n) for1(j, 1, n) read(a[i][j]);
	CC(vis, -1);
	vis[0][X][Y]=0; int flag=0;
	for1(t, 1, T) {
		for1(i, 1, n) for1(j, 1, n) if(t%a[i][j]==0) {
			rep(k, 8) {
				int fx=dx[k]+i, fy=dy[k]+j;
				if(fx<1 || fy<1 || fx>n || fy>n || vis[flag][fx][fy]!=t-1) continue;
				vis[!flag][i][j]=t;
				break;
			}
		}
		flag=!flag;
	}
	for1(i, 1, n) for1(j, 1, n) if(vis[flag][i][j]==T) ++cnt;
	printf("%d\n", cnt);
	for1(i, 1, n) for1(j, 1, n) if(vis[flag][i][j]==T) printf("%d %d\n", i, j);
	return 0;
}

描述

“骑士的旅行”是最近流行的一种棋盘游戏。N*N的棋盘上,我们于时刻0在第X行、 第Y列的格子上放置一个骑士。每个时刻将骑士按照规则进行一步移动,即某个坐标改变2个单位,同时另一个坐标改变1个单位。游戏规则中,棋盘的每个格子并 不总是可以使用的,具体来说,每个格子都被赋予一个正整数,只有当前的时刻是此正整数的倍数时,这个格子才能使用。当然,游戏过程中的每个时刻,骑士必须 处在一个可以使用的格子上。游戏者需要仔细的设计骑士的移动方案才能让游戏进行下去。

给你一个游戏的初始局面,即棋盘的大小,时刻0骑士的位置,以及每个格子被赋予的正整数,请你计算能否对骑士进行T次操作(即游戏能否进行到时刻T)。如果能,请找出时刻T骑士可能出现的所有位置。

格式

输入格式

第1行,包括两个正整数N,T,分别表示棋盘的大小,和操作次数。

第2行,包括两个正整数X, Y,表示时刻0骑士所处的位置。

第3~N+2行,每行N个不超过10^9的正整数。第i+2行的第j个整数表示棋盘上第i行、第j列的格子被赋予的整数。

输出格式

第一行,包含一个非负整数M,表示T次操作后骑士可能出现的位置总数。

接下来M行,每行包括两个正整数,表示一个骑士可能出现的位置。将这些位置按照行编号递增(行编号相同时按列编号递增)的顺序输出。

样例1

样例输入1[复制]

3 2
1 1
1 3 2
2 3 2
3 1 1

样例输出1[复制]

2
1 1
1 3

限制

1s

提示

对于30%的数据,有1 ≤ T ≤ 50,000;
对于100%的数据,有3 ≤ N ≤ 30,1 ≤ T ≤ 1,000,000,1 ≤ X, Y ≤ N。

来源

COCI 2011/2012

时间: 2024-09-28 20:03:07

【vijos】1791 骑士的旅行(特殊的技巧)的相关文章

A Knight&#39;s Journey(DFS)深搜

A Knight's Journey Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 33634 Accepted: 11450 Description Background The knight is getting bored of seeing the same black and white squares again and again and has decided to make a journey around

【vijos】1746 小D的旅行(dijkstra)

https://vijos.org/p/1746 这题就是水题.裸的跑完每个点的最短路后直接可以暴力出解.. 这题贴出来是因为我改了下我的dijkstra的模板... 注意vis不要提前加.否则你懂的.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #in

【贪心】Vijos P1615 旅行

题目链接: https://vijos.org/p/1615 题目大意: N条路,路的高度给你,走一条路的耗费体力是从上一条路的高度到当前路高度的绝对值差. 可以改变一条路的高度,耗费的体力等于改变前后的路高度差.求最小耗费体力. 题目思路: [贪心] 其实就是求拐点,一个人先下坡在上坡要耗费两次体力,不如直接把山谷改成和两边一样高的,这样答案更优.山顶同理.最后在计算一遍换完高度之后的高度差. 1 // 2 //by coolxxx 3 //#include<bits/stdc++.h> 4

【vijos】1447 开关灯泡(高精度+特殊的技巧)

https://vijos.org/p/1447 一开始想了想似乎只想到了与约数个数有关,即约数个数为奇数那么显然是亮的. 竟然没想到完全平方数..sad.. 在正因子中,只有完全平方数的正因子才是奇数!(包括1和他自己)!!! 在区间[1, n]中,一共有sqrt(n)个完全平方数!(这个多想想就知道了...) 然后就是高精度...高精度的开方不难写,(但是我在我的高精模板上找到了错误good..就是不要memset整个数组,要不然果断tle)二分mid然后验证即可. #include <cs

【vijos】1882 石阶上的砖(中位数+特殊的技巧)

https://vijos.org/p/1882 这种题很赞.. 以后记得这些绝对值最小的优先想中位数啊orz 首先我们将所有的高度都减掉他们的高度差,那么得到的应该是一串高低不平的数列,那么题目转化为,将这个改变后的数列变成一样高的最小费用. 那么显然是中位数啦. 好赞. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream

【vijos】1881 闪烁的繁星(线段树+特殊的技巧)

https://vijos.org/p/1881 这场比赛太难了sad.所以我都没做.. 这题一开始我竟然不会sad(本来就不会),然后我继续yy..yy了好久,竟然yy了个什么可拆分的并查集?(sad,后来发现我是如此sb,根本无法实现..) 然后我弃疗了,比赛干脆不交了..sad 后来看了题解和神犇们热心的指导,这就是一水题.. sad. 我们只需要在线段树维护三个值,L表示这个节点的区间内从左边向又能延伸的最长可行串的长度,R表示这个节点的区间内从右边向左能延伸的最长可行串的长度,mx表示

【vijos】1768 顺序对的值(特殊的技巧)

https://vijos.org/p/1768 之前不知道为什么,我yy了一个n^2的做法,但是没能写出来..sad 然后看了题解才发现这题好神.. 为什么一定要照着题意找两个点然后算呢?这就是问题所在... 我们可以观察每一个点,发现他的贡献恰好是左边比他小的数和右边比他大的数组成的顺序对,那么一共有l*r对,所以答案就加上l*r 这种题的思想很好啊..以后做这些题可以用个体来想整体,orz (还有这题他们说lgn使用树状数组维护l和r,怎么维护啊QAQ #include <cstdio>

cogs 2. 旅行计划 dijkstra+打印路径小技巧

2. 旅行计划 ★★   输入文件:djs.in   输出文件:djs.out   简单对比时间限制:3 s   内存限制:128 MB [题目描述] 过暑假了,阿杜准备出行旅游,他已经查到了某些城市的两两之间的距离及可行路线(可行路线有方向),如下图所示.请你编程计算从阿杜所住城市到其它城市的最短路径以帮助阿杜制定旅行计划. [输入格式] 输入由若干行组成,第一行有三个整数 n(1≤n≤100) 为城市数,m(1≤m≤n2) 为城市间道路数,s(0≤s≤n−1) 是阿杜所住城市.第 2 至 m

vijos 1780 开车旅行

细节巨多. 倍增即可. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<set> #include<cmath> #include<cstdlib> #define maxv 200500 #define maxn 100500 #define eps 1e-7 #define inf 0x7f7f7f7f