您的位置:首页 > 其它

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();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: