【POJ】1739 Tony's Tour

http://poj.org/problem?id=1739

题意:n×m的棋盘,‘#‘是障碍,‘.‘是空白,求左下角走到右下角且走过所有空白格子的方案数。(n,m<=8)

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

typedef long long ll;
#define BIT(a,b) ((a)<<((b)<<1))
#define CLR(a,b) (a^=((a)&BIT(3,b)))
#define GET(a,b) (((a)>>((b)<<1))&3)
int n, m, all, lastx, lasty;
bool mp[12][12];

int find(int col, int flag, int s) {
	int sum=0;
	if(flag==0) {
		for(int i=col; i>=0; --i) {
			int k=GET(s, i);
			if(k==1) --sum;
			if(k==2) ++sum;
			if(!sum) return i;
		}
	}
	else {
		for(int i=col; i<=m; ++i) {
			int k=GET(s, i);
			if(k==1) ++sum;
			if(k==2) --sum;
			if(!sum) return i;
		}
	}
	return -1;
}
bool next(int s, int row, int col, bool U, bool D, bool L, bool R, int &T) {
	if((col==0 && L) || (col==m-1 && R)) return 0;
	if((row==0 && U) || (row==n-1 && D)) return 0;
	if((D && mp[row+1][col]) || (R && mp[row][col+1])) return 0;
	int l=GET(s, col), u=GET(s, col+1), d=0, r=0;
	if((!l && L) || (!u && U) || (l && !L) || (u && !U)) return 0;
	T=s;
	CLR(T, col);
	CLR(T, col+1);
	if(!l && !u) { if(D && R) d=1, r=2; }
	else if(l && u) {
		if(l==1 && u==1) {
			int pos=find(col+1, 1, s);
			CLR(T, pos);
			T|=BIT(1, pos);
		}
		else if(l==2 && u==2) {
			int pos=find(col, 0, s);
			CLR(T, pos);
			T|=BIT(2, pos);
		}
		else if(l==1 && u==2) { if(row!=lastx || col!=lasty) return 0; }
	}
	else if(l && !u) { if(D) d=l; if(R) r=l; }
	else if(!l && u) { if(D) d=u; if(R) r=u; }
	T|=BIT(d, col);
	T|=BIT(r, col+1); if(col==m-1) T<<=2, T&=all; //printf("t:"); print(T); puts("");
	return 1;
}

struct H {
	static const int M=1000007;
	struct E { int next, to; }e[M];
	int head, cnt, hash[M];
	ll sum[M];
	H() { memset(hash, -1, sizeof hash); memset(sum, 0, sizeof sum); cnt=head=0; }
	bool find(int x, int &pos) {
		pos=x%M;
		while(1) { if(hash[pos]==x) return 0; else if(hash[pos]==-1) break; ++pos; if(pos==M) pos=0; }
		hash[pos]=x;
		return 1;
	}
	void ins(int t, ll d) { int pos; if(!find(t, pos)) { sum[pos]+=d; return; } e[++cnt].next=head; head=cnt; e[cnt].to=pos; sum[pos]=d; }
	void clr() { for(int i=head; i; i=e[i].next) hash[e[i].to]=-1, sum[e[i].to]=0; head=0; cnt=0; }
}T1, T2;

ll bfs() {
	H *q1=&T1, *q2=&T2;
	q1->clr(); q1->ins(0, 1);
	for(int row=0; row<n; ++row) for(int col=0; col<m; ++col) {
		q2->clr();
		for(int i=q1->head; i; i=q1->e[i].next) {
			ll sum=q1->sum[q1->e[i].to];
			int s=q1->hash[q1->e[i].to], t;
			if(mp[row][col]) {
				if(next(s, row, col, 0, 0, 0, 0, t)) q2->ins(t, sum);
			}
			else {
				if(next(s, row, col, 1, 1, 0, 0, t)) q2->ins(t, sum);
				if(next(s, row, col, 1, 0, 1, 0, t)) q2->ins(t, sum);
				if(next(s, row, col, 1, 0, 0, 1, t)) q2->ins(t, sum);
				if(next(s, row, col, 0, 1, 1, 0, t)) q2->ins(t, sum);
				if(next(s, row, col, 0, 1, 0, 1, t)) q2->ins(t, sum);
				if(next(s, row, col, 0, 0, 1, 1, t)) q2->ins(t, sum);
			}
		}
		swap(q1, q2);
	}
	ll ans=0;
	for(int i=q1->head; i; i=q1->e[i].next) ans+=q1->sum[q1->e[i].to];
	return ans;
}

int main() {
	char s[20];
	while(scanf("%d%d", &n, &m), n|m) {
		for(int i=2; i<n+2; ++i) {
			scanf("%s", s+2);
			for(int j=2; j<m+2; ++j) if(s[j]==‘#‘) mp[i][j]=1; else mp[i][j]=0;
		}
		n+=2; m+=4;
		for(int i=0; i<n; ++i) mp[i][1]=mp[i][m-2]=1;
		for(int i=0; i<m; ++i) mp[1][i]=1;
		for(int i=0; i<m; ++i) mp[0][i]=0;
		for(int i=0; i<n; ++i) mp[i][0]=mp[i][m-1]=0;
		mp[n-1][1]=mp[n-1][m-2]=0;
		lastx=n-1; lasty=m-1;
		all=BIT(1, m+1)-1;
		printf("%lld\n", bfs());
	}
	return 0;
}

  



模板题...

将图用墙先封起来,然后开一条小路从左下角旋转到右下角,然后就是裸的求简单回路的问题辣...正确性很显然吧...

【POJ】1739 Tony's Tour

时间: 2024-08-25 11:58:36

【POJ】1739 Tony's Tour的相关文章

【插头DP】 POJ 1739 Tony&#39;s Tour

通道:http://poj.org/problem?id=1739 题意:左下角走到右下角路径数,单回路.做法就是我们新添2行后寻找回路就可以啦 . 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 const int MAX_N = 13; 8 const int MAX_M = 13; 9 const int HASH =

【POJ】【1739】Tony&#39;s Tour

插头DP 楼教主男人八题之一! 要求从左下角走到右下角的哈密顿路径数量. 啊嘞,我只会求哈密顿回路啊……这可怎么搞…… 容易想到:要是把起点和重点直接连上就变成一条回路了……那么我们就连一下~ 我们可以在整张图下面加两行:(例:3*5) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 红色的是原来的起点和终点,下面紫色的路径将这两个点连了起来= =然后这题瞬间就变回了Formula 1那题……求哈密顿回路数量,so easy有没有~(其实不这样

poj 1739 Tony&#39;s Tour 插头dp模板题

题意: 给一个迷宫,求左下角到右下角的路径数. 分析: 插头dp的模板题,建议先看cdq的论文再看代码,这份代码在模板基础上略微有改动.论文地址http://wenku.baidu.com/view/ed2b3e23482fb4daa58d4b74.html 代码: #include <iostream> using namespace std; const int maxD=16; const int HASH=10007; const int STATE=1000024; int N,M;

【POJ】2278 DNA Sequence

各种wa后,各种TLE.注意若AC非法,则ACT等一定非法.而且尽量少MOD. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 7 #define MAXN 105 8 #define NXTN 4 9 10 char str[15]; 11 12 typedef struct Matrix {

【POJ】2449 Remmarguts&#39; Date(k短路)

http://poj.org/problem?id=2449 不会.. 百度学习.. 恩. k短路不难理解的. 结合了a_star的思想.每动一次进行一次估价,然后找最小的(此时的最短路)然后累计到k 首先我们建反向边,跑一次从汇到源的最短路,将跑出来的最短路作为估价函数h 根据f=g+h 我们将源s先走,此时实际价值g为0,估价为最短路(他们的和就是s-t的最短路) 将所有s所连的边都做相同的处理,加入到堆中(假设此时到达的点为x,那么x的g等于s到这个点的边权,因为根据最优,g+h此时是从x

【POJ】2318 TOYS ——计算几何+二分

TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10281   Accepted: 4924 Description Calculate the number of toys that land in each bin of a partitioned toy box. Mom and dad have a problem - their child John never puts his toys away w

【POJ】3009 Curling 2.0 ——DFS

Curling 2.0 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11432   Accepted: 4831 Description On Planet MM-21, after their Olympic games this year, curling is getting popular. But the rules are somewhat different from ours. The game is

【POJ】1056 IMMEDIATE DECODABILITY

字典树水题. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 5 typedef struct Trie { 6 bool v; 7 Trie *next[2]; 8 } Trie; 9 10 Trie *root; 11 12 bool create(char str[]) { 13 int i = 0, id; 14 bool ret = false; 15 Trie *p = root

【POJ】2418 Hardwood Species

简单字典树. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 5 #define MAXN 128 6 7 typedef struct Trie { 8 int count; 9 Trie *next[MAXN]; 10 Trie() { 11 count = 0; 12 for (int i=0; i<MAXN; ++i) 13 next[i] = NULL; 14 } 15 }