【POJ 1739】Tony's Tour


Tony‘s Tour

Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 3545   Accepted: 1653

Description

A square township has been divided up into n*m(n rows and m columns) square plots (1<=N,M<=8),some of them are blocked, others are unblocked. The Farm is located in the lower left plot and the Market is located in the lower right plot. Tony takes her tour of
the township going from Farm to Market by walking through every unblocked plot exactly once.

Write a program that will count how many unique tours Betsy can take in going from Farm to Market.

Input

The input contains several test cases. The first line of each test case contain two integer numbers n,m, denoting the number of rows and columns of the farm. The following n lines each contains m characters, describe the farm. A ‘#‘ means a blocked square,
a ‘.‘ means a unblocked square.

The last test case is followed by two zeros.

Output

For each test case output the answer on a single line.

Sample Input

2 2
..
..
2 3
#..
...
3 4
....
....
....
0 0

Sample Output

1
1
4

Source

[email protected]

插头dp。

在方格最后添加.########.  使得原问题转化为回路问题,即【URAL 1519】

..................

为什么不能只添加一行...............呢?

这样可能会使得答案增加!可以蛇形走!

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#define LL long long
#define M 100000+5
using namespace std;
char s[20];
int total[2],tot,now,n,m,pre,bit[20],a[20][20],h[1005];
struct edge
{
	int y,ne;
}e[M];
LL f[2][M],state[2][M],ans;
void Solve(LL s,LL num)
{
	int pos=s%1000;
	for (int i=h[pos];i;i=e[i].ne)
		if (state[now][e[i].y]==s)
		{
			f[now][e[i].y]+=num;
			return;
		}
	total[now]++;
	state[now][total[now]]=s;
	f[now][total[now]]=num;
	e[++tot].y=total[now];
	e[tot].ne=h[pos];
	h[pos]=tot;
}
void Plugdp()
{
	ans=0;
	now=0;
	total[now]=1;
	state[now][1]=0;
	f[now][1]=1;
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=total[now];j++)
			state[now][j]<<=2;
		for (int j=1;j<=m;j++)
		{
			pre=now,now=pre^1;
			memset(h,0,sizeof(h));
			total[now]=0;
			tot=0;
			for (int k=1;k<=total[pre];k++)
			{
				LL s=state[pre][k];
				LL num=f[pre][k];
				int p=(s>>bit[j-1])%4,q=(s>>bit[j])%4;
				if (!a[i][j])
				{
					if (p+q==0) Solve(s,num);
				}
				else if (p+q==0)
				{
					if (a[i][j+1]&&a[i+1][j])
						s=s+(1<<bit[j-1])+2*(1<<bit[j]),
						Solve(s,num);
				}
				else if (!p&&q)
				{
					if (a[i][j+1])
						Solve(s,num);
					if (a[i+1][j])
						s=s-q*(1<<bit[j])+q*(1<<bit[j-1]),
						Solve(s,num);
				}
				else if (p&&!q)
				{
					if (a[i+1][j])
						Solve(s,num);
					if (a[i][j+1])
						s=s-p*(1<<bit[j-1])+p*(1<<bit[j]),
						Solve(s,num);
				}
				else if (p+q==2)
				{
					int b=1;
					for (int t=j+1;t<=m;t++)
					{
						int v=(s>>bit[t])%4;
						if (v==1) b++;
						if (v==2) b--;
						if (!b)
						{
							s-=(1<<bit[t]);
							break;
						}
					}
					s=s-(1<<bit[j-1])-(1<<bit[j]);
					Solve(s,num);
				}
				else if (p+q==4)
				{
					int b=-1;
					for (int t=j-2;t>=0;t--)
					{
						int v=(s>>bit[t])%4;
						if (v==1) b++;
						if (v==2) b--;
						if (!b)
						{
							s+=(1<<bit[t]);
							break;
						}
					}
					s=s-2*(1<<bit[j])-2*(1<<bit[j-1]);
					Solve(s,num);
				}
				else if (p==1&&q==2)
				{
					if (i==n&&j==m)
						ans+=num;
				}
				else if (p==2&&q==1)
				{
					s=s-2*(1<<bit[j-1])-(1<<bit[j]);
					Solve(s,num);
				}
			}
		}
	}
}
int main()
{
	for (int i=0;i<=15;i++)
		bit[i]=i<<1;
	while (scanf("%d%d",&n,&m)!=EOF&&n)
	{
		memset(a,0,sizeof(a));
		for (int i=1;i<=n;i++)
		{
			scanf("%s",s+1);
			for (int j=1;j<=m;j++)
				a[i][j]=s[j]=='.';
		}
		n+=2;
		a[n-1][1]=a[n-1][m]=1;
		for (int j=2;j<m;j++)
			a[n-1][j]=0;
		for (int j=1;j<=m;j++)
			a[n][j]=1;
		Plugdp();
		cout<<ans<<endl;
	}
	return 0;
}

【POJ 1739】Tony's Tour

时间: 2024-10-26 09:42:25

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

【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

Description A square township has been divided up into n*m(n rows and m columns) square plots (1<=N,M<=8),some of them are blocked, others are unblocked. The Farm is located in the lower left plot and the Market is located in the lower right plot. T

【POJ 2750】 Potted Flower(线段树套dp)

[POJ 2750] Potted Flower(线段树套dp) Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4566   Accepted: 1739 Description The little cat takes over the management of a new park. There is a large circular statue in the center of the park, surrou

【POJ 1408】 Fishnet (叉积求面积)

[POJ 1408] Fishnet (叉积求面积) 一个1*1㎡的池塘 有2*n条线代表渔网 问这些网中围出来的最大面积 一个有效面积是相邻两行和相邻两列中间夹的四边形 Input为n 后面跟着四行 每行n个浮点数 每一行分别代表a,b,c,d 如图 并且保证a(i) > a(i-1) b(i) > b(i-1) c(i) > c(i-1) d(i) > d(i-1) n(n <= 30)*2+4(四个岸)条边 枚举点数就行 相邻的四个四个点枚举 找出围出的最大面积 找点用

【POJ 2513】Colored Sticks

[POJ 2513]Colored Sticks 并查集+字典树+欧拉通路 第一次做这么混的题..太混了-- 不过题不算难 字典树用来查字符串对应图中的点 每个单词做一个点(包括重复单词 题意就是每个边走且直走一次(欧拉通路 欧拉图的判定: 没有或者只有两个奇数度的点的图叫做欧拉图 有这些就可以解答此题了 另外需要注意题目范围是25W个木棍 所以最多可能有50W个点 卡了好多个RE 代码如下: #include <iostream> #include <cstdlib> #incl

2292: 【POJ Challenge 】永远挑战

2292: [POJ Challenge ]永远挑战 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 553  Solved: 230[Submit][Status][Discuss] Description lqp18_31和1tthinking经常出题来虐ftiasch.有一天, lqp18_31搞了一个有向图,每条边的长度都是1. 他想让ftiasch求出点1到点 N 的最短路."水题啊.", ftiasch这么说道. 所以1tth

【POJ 1201】 Intervals(差分约束系统)

[POJ 1201] Intervals(差分约束系统) 11 1716的升级版 把原本固定的边权改为不固定. Intervals Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 23817   Accepted: 9023 Description You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn. Write a p

【POJ 1228】Grandpa&#39;s Estate 凸包

找到凸包后暴力枚举边进行$check$,注意凸包是一条线(或者说两条线)的情况要输出$NO$ #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define N 1003 #define read(x) x = getint() using namespace std; inline int getint() { int k = 0, fh = 1; char c

【POJ 2480】Longge&#39;s problem(欧拉函数)

题意 求$ \sum_{i=1}^n gcd(i,n) $ 给定 $n(1\le n\le 2^{32}) $. 链接 分析 用欧拉函数$φ(x)$求1到x-1有几个和x互质的数. gcd(i,n)必定是n的一个约数.若p是n的约数,那么gcd(i,n)==p的有$φ(n/p)$个数,因为要使gcd(i,n)==p,i/p和n/p必须是互质的.那么就是求i/p和n/p互质的i在[1,n]里有几个,就等价于,1/p,2/p,...,n/p里面有几个和n/p互质,即φ(n/p). 求和的话,约数为p