UVA - 225 Golygons

题意:求从原点开始依次走1,2...n步后到回到原点的方案数,其中不能经过障碍,每次必须左右拐

思路:一个比较简单的DFS,结果做了好久

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;

const int MAXN = 250;
const int Add = 100;

int n, ans;
int G[MAXN][MAXN], step[MAXN], sum[MAXN];
int dx[4]={1, 0, 0, -1};
int dy[4]={0, 1, -1, 0};
char sign[5]="ensw";

bool check(int x, int y, int d, int k) {
	for (int i = 1; i <= k; i++) {
		x += dx[d];
		y += dy[d];
		if (abs(x) > Add || abs(y) > Add)
			continue;
		if (G[x+Add][y+Add] == -1)
			return true;
	}
	if (abs(x)+abs(y) > sum[20] - sum[k])
		return true;
	return false;
}

void dfs(int x, int y, int cnt, int last) {
	if (cnt > n) {
		if (x == 0 && y == 0) {
			for (int i = 1; i <= n; i++)
				printf("%c", sign[step[i]]);
			printf("\n");
			ans++;
		}
		return;
	}
	int &i = step[cnt];
	for (i = 0; i < 4; i++) {
		if (i == last || i+last == 3)
			continue;
		if (check(x, y, i, cnt))
			continue;
		int nx = x + dx[i]*cnt;
		int ny = y + dy[i]*cnt;
		if (G[nx+Add][ny+Add])
			continue;
		G[nx+Add][ny+Add] = 1;
		dfs(nx, ny, cnt+1, i);
		G[nx+Add][ny+Add] = 0;
	}
}

int main() {
	sum[0] = 0;
	for (int i = 1; i <= 20; i++)
		sum[i] = sum[i-1] + i;
	int t, k;
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &n, &k);
		memset(G, 0, sizeof(G));
		ans = 0;
		for (int i = 0; i < k; i++) {
			int a, b;
			scanf("%d%d", &a, &b);
			if (abs(a) > Add || abs(b) > Add)
				continue;
			G[a+Add][b+Add] = -1;
		}
		dfs(0, 0, 1, -1);
		printf("Found %d golygon(s).\n\n", ans);
	}
	return 0;
}

UVA - 225 Golygons

时间: 2025-01-13 20:04:56

UVA - 225 Golygons的相关文章

UVa 225 Golygons 题解

难度:β 建议用时:40 min 关于这道题目的背景在维基百科上有.很神奇. 但是我们的这道题没有那么多考虑.上来直接东南西北狂搜一通就好了. 算法很简单,直接上过程. 首先确定 "东""南""西""北" 对应的英文字母 "e""s""w""n". 因为题目还说不能后退,所以要把后退的方向也处理出来."东"对"西&qu

Automatic Editing UVA 10115

#include <stdio.h> #include <string.h> #define MAXL 225+5 #define MAXN 10+5 char find[MAXN][MAXL],replace[MAXN][MAXL]; char text[MAXL],convert[MAXL]; int Find(int,int*); void Replace(int,int); int str_cmp(int,int); int main(){ int N,i,j,k; int

uva 704

自己之前的不见了.. 这题是双向广搜即可过.. 1 // Colour Hash (色彩缤纷游戏) 2 // PC/UVa IDs: 110807/704, Popularity: B, Success rate: average Level: 3 3 // Verdict: Accepted 4 // Submission Date: 2011-08-28 5 // UVa Run Time: 0.048s 6 // 7 // 版权所有(C)2011,邱秋.metaphysis # yeah

UVA 10581 - Partitioning for fun and profit(数论递推)

10581 - Partitioning for fun and profit 题目链接 题意:给定m, n,表示分配给n个格子,分配m个数字进去,每个格子最少1,并且序列要是递增的,问第k个字典序的序列是什么 思路:先利用dp打出表,dp[i][j][k]表示第i个数,尾巴为j,总和剩下k的情况,写一个记忆化求出,之后在这个数组基础上,从左往右枚举要放那个数字合适,合适的就放进去并且输出,注意最后一个数字要单独输出. 代码: #include <cstdio> #include <cs

Fast Matrix Operations(UVA)11992

UVA 11992 - Fast Matrix Operations 给定一个r*c(r<=20,r*c<=1e6)的矩阵,其元素都是0,现在对其子矩阵进行操作. 1 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素add上val: 2 x1 y1 x2 y2 val 表示将(x1,y1,x2,y2)(x1<=x2,y1<=y2)子矩阵中的所有元素set为val: 3 x1 y1 x2 y2 val 表示输

UVa 568 Just the Facts

A过去后看了一下别人的解法,发现除了打表还有一种数论的方法. 分析一下阶乘后面的0是怎么出现的呢,当然是2乘5得到的. 我们将1~N先放在一个数组里面. 从数组第一个元素开始,先统计一下N!中因子为5的个数记为count,将其除去,然后再除去count个2.这样一来的话把所有元素乘起来后就不会出现10的倍数了. 当然并不是真正的乘起来,那样的话肯定是要溢出的,因为只关心最后一位数,所以每次乘完后求10的余数即可. 我的做法是打表,因为题目里给了N <= 10000的条件限制,所以可以把1~100

UVA 562 Dividing coins --01背包的变形

01背包的变形. 先算出硬币面值的总和,然后此题变成求背包容量为V=sum/2时,能装的最多的硬币,然后将剩余的面值和它相减取一个绝对值就是最小的差值. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int c[102],d

UVA 10341 Solve It

Problem F Solve It Input: standard input Output: standard output Time Limit: 1 second Memory Limit: 32 MB Solve the equation: p*e-x + q*sin(x) + r*cos(x) + s*tan(x) + t*x2 + u = 0 where 0 <= x <= 1. Input Input consists of multiple test cases and te

UVA 11014 - Make a Crystal(容斥原理)

UVA 11014 - Make a Crystal 题目链接 题意:给定一个NxNxN的正方体,求出最多能选几个整数点.使得随意两点PQ不会使PQO共线. 思路:利用容斥原理,设f(k)为点(x, y, z)三点都为k的倍数的点的个数(要扣掉一个原点O).那么全部点就是f(1),之后要去除掉共线的,就是扣掉f(2), f(3), f(5)..f(n).n为素数.由于这些素数中包括了合数的情况,而且这些点必定与f(1)除去这些点以外的点共线,所以扣掉.可是扣掉后会扣掉一些反复的.比方f(6)在f