您的位置:首页 > 其它

hdu 4856 Tunnels(动态规划&状态压缩)

2014-07-30 22:15 399 查看
题意:给出一个图,上面有一些通道,每个通道通过且至少通过一次,求最少需要花费的时间。

思路:首先求出各个通道之间的距离,题目变成如上所述的一个问题。用二进制描述状态,dp求解。

写状态转移方程的时候,我一直写成四重循环,提交TLE。后来想到了可以去掉一重循环,然后提交各种wa。我想了好长时间换了各种写法,还是找不到错哪儿了。最后发现是因为i<=m我写成了i<m,白忙活了两个小时……

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int N=16;
const int MAX=0x3f3f3f3f;
char s

;
int dp
[35000],mark

,vis

,st
;
int n,m;
int dir[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
struct node
{
int x,y;
int step;
} q[N*N];
struct ff
{
int x1,y1;
int x2,y2;
} a
;
int Min(int x,int y)
{
if(x<y) return x;
else return y;
}
int judge(int x,int y)
{
if(x>=1&&x<=n&&y>=1&&y<=n&&vis[x][y]==0&&s[x][y]=='.') return 1;
else return 0;
}
int bfs(ff s,ff e)
{
int head,tail;
head=tail=0;
q[tail].x=s.x2,q[tail].y=s.y2,q[tail++].step=0;
vis[s.x2][s.y2]=1;
while(head!=tail)
{
node cur,next;
cur=q[head++];
if(cur.x==e.x1&&cur.y==e.y1)
return cur.step;
for(int i=0; i<4; i++)
{
next.x=cur.x+dir[i][0];
next.y=cur.y+dir[i][1];
next.step=cur.step+1;
if(judge(next.x,next.y))
{
vis[next.x][next.y]=1;
q[tail++]=next;
}
}
}
return MAX;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
getchar();
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
scanf("%c",&s[i][j]);
getchar();
}
for(int i=1; i<=m; i++)
scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
for(int i=1; i<=m; i++)
{
for(int j=1; j<=m; j++)
{
memset(vis,0,sizeof(vis));
mark[i][j]=bfs(a[i],a[j]);
}
}
memset(dp,0x3f,sizeof(dp));
int t=(1<<m);
for(int i=1; i<=m; i++)
{
st[i]=(1<<(i-1));
dp[i][st[i]]=0;
}
for(int i=1; i<t; i++)
{
for(int j=1; j<=m; j++)
{
if((i&st[j])!=0) continue;
for(int k=1; k<=m; k++)
{
if(mark[k][j]==MAX) continue;
if(dp[k][i]==MAX) continue;
dp[j][i|st[j]]=Min(dp[j][i|st[j]],dp[k][i]+mark[k][j]);
}
}
}
int min=MAX;
for(int i=1; i<=m; i++)
min=Min(min,dp[i][t-1]);
if(min==MAX) printf("-1\n");
else printf("%d\n",min);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: