URAL 1519 Formula 1 【插头DP模板题】
2016-09-29 12:01
316 查看
题意就是给出一个带障碍的n*m的格子,求有多少条回路恰好经过每个非障碍格子一次?
思路:
插头DP学自插头DP写这道题的时候几个地方处理不当,调了许久的bug。
代码:(最小表示法)
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<map> #include<string> #include<queue> #include<vector> #include<list> #include<bitset> //#pragma comment(linker,"/STACK:1024000000,1024000000") using namespace std; typedef long long ll; #define INF 0x3f3f3f3f const int HASH=30007; const int STATE=1000010; struct HASHMAP { int head[HASH],next[STATE],size; long long state[STATE]; long long f[STATE]; void init() { size=0; memset(head,-1,sizeof(head)); } void push(long long st,long long ans) { int i; int h=st%HASH; for(i=head[h];i!=-1;i=next[i])//这里要注意是next if(state[i]==st) { f[i]+=ans; return; } state[size]=st; f[size]=ans; next[size]=head[h]; head[h]=size++; } }hm[2]; char Mp[20][20]; int n,m; int ex,ey; void encode(ll &code,int a[]) { code=0; for(int i=m; i>=0; i--) { code<<=3; code|=(ll)a[i]; } } void uncode(ll code,int a[]) { for(int i=0; i<=m; i++) { a[i]=code&7; code>>=3; } } void add(int a[],int c) { int val=1; for(int i=0; i<c; i++) val=max(val,a[i]+1); for(int i=c+1; i<=m; i++) if(a[i]>=val) a[i]++; a[c]=a[c+1]=val; } void Merge(int a[],int c) { int val=min(a[c],a[c+1]); int Max=max(a[c],a[c+1]); a[c]=a[c+1]=0; for(int i=0; i<=m; i++) { if(a[i]==Max) a[i]=val; if(a[i]>Max) a[i]--; } } void show(int a[]) { for(int i=0;i<=m;i++) printf("%d%c",a[i],i==m?'\n':' '); } void dpblank(int x,int y,int cur) { int a[20]; ll code; HASHMAP &now=hm[cur]; HASHMAP &to=hm[cur^1]; for(int i=0;i<now.size;i++) { uncode(now.state[i],a); if(!a[y]&&!a[y+1]) { if(x==n-1||y==m-1||Mp[x+1][y]=='*'||Mp[x][y+1]=='*') continue; add(a,y); encode(code,a); if(y==m-1) code<<=3; to.push(code,now.f[i]); } else if(!a[y]&&a[y+1]||a[y]&&!a[y+1]) { int val=max(a[y],a[y+1]); if(x!=n-1&&Mp[x+1][y]=='.') { a[y]=val,a[y+1]=0; encode(code,a); if(y==m-1) code<<=3; to.push(code,now.f[i]); } if(y!=m-1&&Mp[x][y+1]=='.') { a[y]=0,a[y+1]=val; encode(code,a); to.push(code,now.f[i]); } } else { if(a[y]==a[y+1]&&!(x==ex&&y==ey)) continue; Merge(a,y); encode(code,a); if(y==m-1) code<<=3; to.push(code,now.f[i]); } } } void dpblock(int x,int y,int cur) { int a[20]; ll code; HASHMAP &to=hm[cur^1]; HASHMAP &now=hm[cur]; for(int i=0;i<now.size;i++) { code=now.state[i]; if(y==m-1) code<<=3; to.push(code,now.f[i]); } } void solve() { int cur=0; ll ans=0; hm[cur].init(); hm[cur].push(0,1); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { hm[cur^1].init(); if(Mp[i][j]=='.') dpblank(i,j,cur); else dpblock(i,j,cur); cur^=1; } int a[20]; if(hm[cur].size) ans=hm[cur].f[0]; printf("%I64d\n",ans); } int main() { while(~scanf("%d%d",&n,&m)) { ex=ey=-1; getchar(); for(int i=0; i<n; i++) gets(Mp[i]); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { if(Mp[i][j]=='.') ex=i,ey=j; } if(ex<0){puts("0");continue;} solve(); } }
代码2:(括号表示法)
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<map> #include<string> #include<queue> #include<vector> #include<list> #include<bitset> //#pragma comment(linker,"/STACK:1024000000,1024000000") using namespace std; typedef long long ll; #define INF 0x3f3f3f3f const int HASH=30007; const int STATE=1000010; struct HASHMAP { int head[HASH],next[STATE],size; long long state[STATE]; long long f[STATE]; void init() { size=0; memset(head,-1,sizeof(head)); } void push(long long st,long long ans) { int i; int h=st%HASH; for(i=head[h];i!=-1;i=next[i])//这里要注意是next if(state[i]==st) { f[i]+=ans; return; } state[size]=st; f[size]=ans; next[size]=head[h]; head[h]=size++; } }hm[2]; char Mp[20][20]; int n,m; int ex,ey; void encode(ll &code,int a[]) { code=0; for(int i=m; i>=0; i--) { code<<=2; code|=(ll)a[i]; } } void uncode(ll code,int a[]) { for(int i=0; i<=m; i++) { a[i]=code&3; code>>=2; } } void add(int a[],int c) { a[c]=1; a[c+1]=2; } void Merge(int a[],int c) { int num=0; if(a[c]==1&&a[c+1]==1) { for(int i=c+1;i<=m;i++) { if(a[i]==1) num++; else if(a[i]==2) num--; if(num==0&&a[i]==2) { a[i]=1;break; } } } else if(a[c]==2&&a[c+1]==2) { for(int i=c;i>=0;i--) { if(a[i]==2) num++; else if(a[i]==1) num--; if(num==0&&a[i]==1) { a[i]=2;break; } } } a[c]=a[c+1]=0; } void show(int a[]) { for(int i=0;i<=m;i++) printf("%d%c",a[i],i==m?'\n':' '); } void dpblank(int x,int y,int cur) { int a[20]; ll code; HASHMAP &now=hm[cur]; HASHMAP &to=hm[cur^1]; for(int i=0;i<now.size;i++) { uncode(now.state[i],a); if(!a[y]&&!a[y+1]) { if(x==n-1||y==m-1||Mp[x+1][y]=='*'||Mp[x][y+1]=='*') continue; a[y]=1,a[y+1]=2; encode(code,a); if(y==m-1) code<<=2; to.push(code,now.f[i]); } else if(!a[y]&&a[y+1]||a[y]&&!a[y+1]) { int val=max(a[y],a[y+1]); if(x!=n-1&&Mp[x+1][y]=='.') { a[y]=val,a[y+1]=0; encode(code,a); if(y==m-1) code<<=2; to.push(code,now.f[i]); } if(y!=m-1&&Mp[x][y+1]=='.') { a[y]=0,a[y+1]=val; encode(code,a); to.push(code,now.f[i]); } } else { if(a[y]==1&&a[y+1]==2&&!(x==ex&&y==ey)) continue; // cout<<x<<' '<<y<<endl; // show(a); Merge(a,y); // show(a); // puts("---------------"); encode(code,a); if(y==m-1) code<<=2; to.push(code,now.f[i]); } } } void dpblock(int x,int y,int cur) { int a[20]; ll code; HASHMAP &to=hm[cur^1]; HASHMAP &now=hm[cur]; for(int i=0;i<now.size;i++) { code=now.state[i]; if(y==m-1) code<<=2; to.push(code,now.f[i]); } } void solve() { int cur=0; ll ans=0; hm[cur].init(); hm[cur].push(0,1); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { hm[cur^1].init(); if(Mp[i][j]=='.') dpblank(i,j,cur); else dpblock(i,j,cur); cur^=1; } int a[20]; if(hm[cur].size) ans=hm[cur].f[0]; printf("%I64d\n",ans); } int main() { while(~scanf("%d%d",&n,&m)) { ex=ey=-1; getchar(); for(int i=0; i<n; i++) gets(Mp[i]); for(int i=0;i<n;i++) for(int j=0;j<m;j++) { if(Mp[i][j]=='.') ex=i,ey=j; } if(ex<0){puts("0");continue;} solve(); } }
相关文章推荐
- 【Ural1519】Formula 1 插头DP模板
- bzoj1814 Ural 1519 Formula 1(插头dp模板题)
- 【URAL 1519】【插头dp模板】Formula 1
- [BZOJ]1814 Ural 1519 Formula 1 插头DP
- ural 1519 Formula 1(插头dp)
- URAL1519 Formula 1 【插头dp】
- Ural1519 Formula 1 插头dp
- ural 1519 Formula 1 插头dp 一条回路
- [省选前题目整理][URAL 1519]Formula 1(插头DP)
- URAL 1519 Formula 1 dp(插头)
- ural 1519 Formula 1(插头dp)
- 【BZOJ1814】Ural 1519 Formula 1 插头DP
- Ural1519 Formula 1 插头dp入门
- URAL 1519 Formula 1 (插头DP,常规)
- URAL - 1519 Formula 1 (插头DP)
- [ural1519]Formula 1 && 插头DP(括号表示法)
- Ural 1519 Formula 1 插头DP(单回路)
- ural 1519 Formula 1(轮廓线|插头DP|括号配对)
- URAL1519 Formula 1(插头dp的基础题 ——详细解释)
- [ural1519]Formula 1 && 插头DP