Ural 1519

原创 2013年12月05日 00:09:53

Ural 1519

真-插头DP模板题,也是用插头DP的思想做的,括号表示法耗时比最小表示法略少,但是思路复杂小小,代码好难打啊,弄了很久才AC。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<queue>

using namespace std;

#define inf 0x7fffffff
#define N 600007
#define LL long long

LL str[20];
LL maps[20][20],n,m;
LL ex,ey;

struct hashmap
{
	LL visit[N],next[N];
	LL h[N];
	LL num[N],cnt;
	void clear()
	{
		cnt = 0;
		memset(visit,-1,sizeof(visit));
	}
	void insert(LL x,LL y)
	{
		LL z = x%N;
		for(LL i = visit[z];i != -1;i = next[i])
		{
			if(h[i] == x)
			{
				num[i] += y;
				return ;
			}
		}
		next[cnt] = visit[z];
		num[cnt] = y;
		h[cnt] = x;
		visit[z] = cnt++;
		return ;
	}
}s[2];

void change(LL x,LL len)                             //数字变数组
{
	LL mark = 3;
	for(LL i = 0;i <= len;i++)
	{
		str[i] = x&mark;
		x >>= 2;
	}
}

LL changeover(LL len)                                 //数组转数字
{
	LL ans = 0;
	for(LL i = len;i >= 0;i--)
	{
		ans <<= 2;
		ans |= str[i];
	}
	return ans;
}

void get(LL len)                                       //换行
{
	for(LL i = len;i >= 1;i--)
	{
		str[i] = str[i - 1];
	}
	str[0] = 0;
}

LL fin(LL len,LL a)                                    //寻找匹配括号
{
	LL i,j;
	LL x;
	if(str[a] == 1)
	{
		for(i = a + 1,j = 0;i <= len;i++)
		{
			if(str[i] == 1)
				j++;
			if(str[i] == 2)
			{
				if(j == 0)
				{
					x = i;
					break;
				}
				else
					j--;
			}
		}
	}
	else
	{
		for(i = a - 1,j = 0;i >= 0;i--)
		{
			if(str[i] == 2)
				j++;
			if(str[i] == 1)
			{
				if(j == 0)
				{
					x = i;
					break;
				}
				else
					j--;
			}
		}
	}
	return x;
}

void adjust(LL len,LL a,LL b)                                 //调整括号匹配
{
	LL x = fin(len,a),y = fin(len,b);
	if(x < y)
	{
		str[x] = 1;
		str[y] = 2;
	}
	else
	{
		str[x] = 2;
		str[y] = 1;
	}
}

void dp(LL last,LL nxt,LL i,LL j,LL k)
{
	change(s[last].h[k],m);
	if(str[j] && str[j + 1] )
	{
		if(maps[i][j + 1])
				return ;
		if(str[j] == 1 && str[j + 1] == 2)
		{
			if(i == ex && j + 1 == ey)
			{
				str[j] = str[j + 1] = 0;
				if(j == m - 1)
					get(m);
				s[nxt].insert(changeover(m),s[last].num[k]);
			}
			else return ;
		}
		else
		{
			adjust(m,j,j + 1);
			str[j] = str[j + 1] = 0;
			if(j == m - 1)
					get(m);
			s[nxt].insert(changeover(m),s[last].num[k]);
		}
	}
	else if(str[j] || str[j + 1])
	{
		if(maps[i][j + 1] == 1)
			return ;
		LL t = max(str[j],str[j + 1]);
		str[j] = t;
		str[j + 1] = 0;
		if(j == m - 1)
		{
			get(m);
			s[nxt].insert(changeover(m),s[last].num[k]);
		}
		else
		{
			s[nxt].insert(changeover(m),s[last].num[k]);
			str[j] = 0;
			str[j + 1] = t;
			s[nxt].insert(changeover(m),s[last].num[k]);
		}
	}
	else
	{
		if(maps[i][j + 1] == 1)
		{
			if(j == m - 1)
			{
				get(m);
			}
			s[nxt].insert(changeover(m),s[last].num[k]);
		}
		else
		{
			if(j == m - 1)
				return ;
			str[j] = 1;str[j + 1] = 2;
			s[nxt].insert(changeover(m),s[last].num[k]);
		}
	}
}

LL solve()
{
	if(ex + ey == -2)
		return 0;
	LL i,j,k,l,flag = 0,nxt;
	s[flag].clear();
	s[flag].insert(0,1);
	for(i = 1;i <= n;i++)
	{
		for(j = 0;j < m;j++)
		{
			nxt = flag^1;
			s[nxt].clear();
			for(k = 0;k < s[flag].cnt;k++)
			{
				dp(flag,nxt,i,j,k);
			}
			flag ^= 1;
		}
	}
	for(i = 0;i < s[nxt].cnt;i++)
	{
		if(s[nxt].h[i] == 0)
			return s[nxt].num[i];
	}
	return 0;
}

int main()
{
	while(cin>>n>>m)
	{
		ex = ey = -1;
		char x;
		for(LL i = 1;i <= n;i++)
		{
			for(LL j = 1;j <= m;j++)
			{
				cin>>x;
				if(x == '*')
				{
					maps[i][j] = 1;
				}
				else
				{
					ex = i;
					ey = j;
					maps[i][j] = 0;
				}
			}
		}
		cout<<solve()<<endl;
	}
    return 0;
}


相关文章推荐

[COGS 1512][URAL 1519]一级方程式赛车

插头DP

URAL 1519. Formula 1

1519. Formula 1 Time limit: 1.0 second Memory limit: 64 MB Background Regardless of the ...

URAL 1519 Formula 1 dp(插头)

题意:给出n*m的方格,有些格子不能铺线,其它格子必须铺,形成一个闭合回路。问有多少种铺法?解:4进制状压表示,用m+1位表示轮廓线上的m个位置的情况。0表示没有插头与线相交,1表示插头’左’,2表示...

Ural1519 Formula 1 插头dp入门

看了几天才懂,自己也说不太清楚,推荐看CDQ的论文基于连通性状态压缩的动态规划问题 这个看完之后这里有一篇比较详细的解题报告http://blog.sina.com.cn/s/blog_51cea4...

URAL 1519 Formula 1(插头DP)

1519. Formula 1 Time limit: 1.0 second Memory limit: 64 MB Background Regardless of the fact, th...
  • Yasola
  • Yasola
  • 2017年07月31日 13:52
  • 189

插头DP——从不会到入门(POJ 2411,HDU 1565,HDU 2167,HDU 1693,Ural 1519)

#include #include #include #include using namespace std; #define LL long long const int maxn=10...
  • kbdwo
  • kbdwo
  • 2013年11月10日 17:01
  • 9419

ural1519 Formula 1

题意:求一些格子不能经过,可以经过的格子要经过的回路个数。。 插头DP入门题。。...

Ural1519 Formula 1 插头dp

原题:Ural1519Ural1519:n*m有障碍矩阵,求单回路覆盖所有无障碍点方案数/————————————————- 插头dp单回路裸模板题...
  • chbug
  • chbug
  • 2016年07月10日 22:07
  • 87

Ural 1519 Formula 1 插头DP

写了三天!终于AC了! 开始的时候无限TLE 然后发现要用hash 然后自己写了hash 然后...

Ural 1519 Formula 1 基于连通性的状态压缩动态规划

2kb代码#include #define mask 600000 #define N 15 #define Hash 1999987 #define mc(p) memset(p,0,sizeof...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Ural 1519
举报原因:
原因补充:

(最多只允许输入30个字)