记录编号 417502 评测结果 AAA
题目名称 [UVa 11443] 网格里的树 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 1.056 s
提交时间 2017-06-25 20:16:26 内存使用 9.55 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
using namespace std;
int T,n,m,mod;
char s[410][20];
int inc(int x,int y){x+=y;return x>=mod?x-mod:x;}
struct state{
	int fa[8],size[8];
	void init(int S){
		for (int i=0;i<m;i++)
			size[i]=0;
		for (int i=0;i<m;i++){
			fa[i]=(S>>(i+i+i)&7);
			size[fa[i]]++;
		}
	}
	void remark(){
		static int Min[9];
		for (int i=0;i<=m;i++) Min[i]=-1;
		for(int i=0;i<m;i++){
			if(Min[fa[i]]==-1) Min[fa[i]]=i;
			fa[i]=Min[fa[i]];
		}
	}
	bool test(int x,int y,bool up,bool left){
		//判断该种连接方式是否合法 
		if (!x&&up) return 0;//连出边界 
		if (!y&&left) return 0;//连出边界 
		if (x&&!up&&size[fa[y]]==1) return 0;//上方的点孤立了 
		if (up&&left){
			if (fa[y-1]==fa[y]) return 0;//成环 
			int S=fa[y];fa[y]=fa[y-1];
			for (int i=0;i<m;i++)
				if (fa[i]==S) fa[i]=fa[y-1];
			remark();
			return 1;
		}
		if (up) return 1;
		if (left) fa[y]=fa[y-1];
			else fa[y]=m;
		remark();
		return 1;
	}
	int val(){
		int S=0;
		for (int i=0;i<m;i++) S|=fa[i]<<(i+i+i);
		return S;
	}
	void print(){
		for (int i=0;i<m;i++) printf("%d ",fa[i]);
	}
};
const int N=1e6+10;
struct hash_map{
	int q[N],val[N],key[N],size;
	hash_map(){memset(key,-1,sizeof key);}
	int hash(int x){
		int ans=0;
		for (int i=x;i;i/=13) ans=ans*23+i%13;
		ans%=N;
		if (ans<0) ans+=N;
		while (key[ans]!=-1&&key[ans]!=x) ans==N-1?ans=0:ans++;
		return ans;
	}
	bool count(int x){
		return key[hash(x)]!=-1;
	}
	int& operator [] (int x){
		int ans=hash(x);
		if (key[ans]==-1){
			key[ans]=x;
			q[++size]=ans;
			val[ans]=0;
		}
		return val[ans];
	}
	void clear(){
		while (size) key[q[size--]]=-1;
	}
};
typedef pair<int,int> pii;
struct table{
	hash_map M;
	//map<int,int> M;
	vector<pii> v;//first表示其状态,second为方案数 
	void clear(){
		M.clear();
		v.clear();
	}
	void insert(int S,int k){//给S状态方案数+k 
		if (!M.count(S)){
			M[S]=v.size();
			v.push_back(pii(S,k));
		}
		else{
			int &val=v[M[S]].second;
			val=inc(val,k);
		}
	}
	int val(int S){
		if (!M.count(S)) return 0;
		return v[M[S]].second;
	}
}dp[2],*x=&dp[0],*y=&dp[1];
bool left_edge[210][20],up_edge[210][20];
void extend(int i,int j){
	y->clear();
	state S,T;
	for (int a=0;a<x->v.size();a++){
		S.init(x->v[a].first);
		int val=x->v[a].second;
		for (int up=up_edge[i][j];up<=1;up++)
		for (int left=left_edge[i][j];left<=1;left++){
			T=S;
			if (T.test(i,j,up,left))
				y->insert(T.val(),val);
		}
	}
	swap(x,y);
	/*printf("add (%d,%d)\n",i,j);
	for (int i=0;i<x->v.size();i++){
		S.init(x->v[i].first);
		S.print();
		printf("cases: %d\n",x->v[i].second);
	}*/
}
int main()
{
	freopen("treeinagrid.in","r",stdin);
	freopen("treeinagrid.out","w",stdout);
	scanf("%d",&T);
	while (T--){
		scanf("%d%d%d",&n,&m,&mod);
		memset(s,0,sizeof s);
		for (int i=0;i<n*2-1;i++) scanf("%s",s[i]);
		for (int i=0;i<n;i++)
		for (int j=0;j<m;j++){
			left_edge[i][j+1]=(s[i<<1][j<<1|1]=='-');
			up_edge[i+1][j]=(s[i<<1|1][j<<1]=='|');
		}
		x->clear();
		x->insert(0,1);
		for (int i=0;i<n;i++)
		for (int j=0;j<m;j++)
			extend(i,j);
		if (!x->M.count(0)) puts("Impossible");
			else printf("%d\n",x->val(0));
	}
	return 0;
}