记录编号 |
417502 |
评测结果 |
AAA |
题目名称 |
[UVa 11443] 网格里的树 |
最终得分 |
100 |
用户昵称 |
FoolMike |
是否通过 |
通过 |
代码语言 |
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;
}