FZU 1977 Pandora adventure
2014-05-13 15:08
155 查看
单回路数,有三种格子,
1.必须走
2.可以走
3.不可以走
求回路数。
还是同样道理,每一个状态增加一个标志位来记录是否形成回路。
1.必须走
2.可以走
3.不可以走
求回路数。
还是同样道理,每一个状态增加一个标志位来记录是否形成回路。
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; const int MAXD=15; const int HASH=50007; const int STATE=100010; int N,M; int code[MAXD]; int maze[MAXD][MAXD];//0表示障碍点,1表示非必走点,2表示必走点 int ch[MAXD]; int isend;//是否形成回路标记位 struct HASHMAP { int head[HASH],next[STATE],size; long long state[STATE],f[STATE]; void init() { size=0; memset(head,-1,sizeof(head)); } void push(long long st,long long ans) { int i,h=st%HASH; for(i=head[h];i!=-1;i=next[i]) if(state[i]==st) { f[i]+=ans; return; } state[size]=st; f[size]=ans; next[size]=head[h]; head[h]=size++; } }hm[2]; void decode(int *code,int m,long long st)//注意要增加一个isend标记位 { for(int i=m;i>=0;i--) { code[i]=st&7; st>>=3; } isend=st&1;//isend标记位在st的最高一位 } long long encode(int *code,int m)//增加isend标记位 { long long st=isend;//最高位 int cnt=1; memset(ch,-1,sizeof(ch)); ch[0]=0; for(int i=0;i<=m;i++) { if(ch[code[i]]==-1)ch[code[i]]=cnt++; code[i]=ch[code[i]]; st<<=3; st|=code[i]; } return st; } void shift(int *code,int m) { for(int i=m;i>0;i--)code[i]=code[i-1]; code[0]=0; } void dpblank(int i,int j,int cur) { int k,left,up; for(k=0;k<hm[cur].size;k++) { decode(code,M,hm[cur].state[k]); left=code[j-1]; up=code[j]; if(isend) {//如果已经形成环路,后面又有插头或者有必过点,则是非法的 if(left||up||maze[i][j]==2)continue; code[j-1]=code[j]=0; if(j==M)shift(code,M); hm[cur^1].push(encode(code,M),hm[cur].f[k]); continue; } if(left&&up) { if(left==up) { code[j-1]=code[j]=0; isend=1; if(j==M)shift(code,M); hm[cur^1].push(encode(code,M),hm[cur].f[k]); } else //不在一个连通分量则合并 { code[j-1]=code[j]=0; for(int t=0;t<=M;t++) if(code[t]==up) code[t]=left; if(j==M)shift(code,M); hm[cur^1].push(encode(code,M),hm[cur].f[k]); } } else if((left&&(!up))||((!left)&&up)) { int t; if(left)t=left; else t=up; if(maze[i][j+1]) { code[j-1]=0; code[j]=t; hm[cur^1].push(encode(code,M),hm[cur].f[k]); } if(maze[i+1][j]) { code[j-1]=t; code[j]=0; if(j==M)shift(code,M); hm[cur^1].push(encode(code,M),hm[cur].f[k]); } } else { if(maze[i][j+1]&&maze[i+1][j]) { code[j-1]=code[j]=13; hm[cur^1].push(encode(code,M),hm[cur].f[k]); } if(maze[i][j]==1)//可以经过可以不经过的点 { code[j-1]=code[j]=0; if(j==M)shift(code,M); hm[cur^1].push(encode(code,M),hm[cur].f[k]); } } } } void dpblock(int i,int j,int cur) { int k; for(k=0;k<hm[cur].size;k++) { decode(code,M,hm[cur].state[k]); code[j-1]=code[j]=0; if(j==M)shift(code,M); hm[cur^1].push(encode(code,M),hm[cur].f[k]); } } char str[20]; void init() { scanf("%d%d",&N,&M); memset(maze,0,sizeof(maze)); for(int i=1;i<=N;i++) { scanf("%s",&str); for(int j=1;j<=M;j++) { if(str[j-1]=='*')maze[i][j]=1; else if(str[j-1]=='O')maze[i][j]=2; } } } void solve() { int i,j,cur=0; hm[cur].init(); hm[cur].push(0,1); for(int i=1;i<=N;i++) for(int j=1;j<=M;j++) { hm[cur^1].init(); if(maze[i][j])dpblank(i,j,cur); else dpblock(i,j,cur); cur^=1; } long long ans=0; for(i=0;i<hm[cur].size;i++) ans+=hm[cur].f[i]; printf("%I64d\n",ans); } int main() { /*freopen("in.txt","r",stdin); freopen("out.txt","w",stdout);*/ int T; int iCase=0; scanf("%d",&T); while(T--) { iCase++; printf("Case %d: ",iCase); init(); solve(); } return 0; }
相关文章推荐
- FZU 1046 Tempter of the Bone
- FZU 2254 英语考试 (最小生成树)(福州大学第十四届程序设计竞赛)
- [fzu 2271]不改变任意两点最短路至多删的边数
- FZU 2271 X (Floyd)(第七届福建省大学生程序设计竞赛)
- FZU 2253 DP(最大子段和变形)
- [fzu 2282]置换不动点大于等于k的排列数
- fzu Problem 2275 Game(kmp)
- FZU 2109 奇偶
- 迷宫------FZU - 2256 (利用 Vector数组基本用法与模拟建树)&&(dfs对树的深度遍历找最短路)
- 英语考试FZU(最小生成树)
- 过河 FZU - 2255 dp
- 函数求解 FZU - 2206
- FZU 2282 错排
- FZU 2278 期望
- FZU 2191 完美的数字 <数学找规律>
- FZU-2195 检查站点
- 2017年福建省赛 FZU - 2271 X(floyd)
- -----FZU 2150-Fire Game
- FZU - 2109 Mountain Number
- FZU 2273 Triangles(判断线段相交和点在多变形内)