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

来源:互联网 发布:魔改坊贞德淘宝 编辑:程序博客网 时间:2024/06/06 18:59

        题意:给出一个图,上面有一些通道,每个通道通过且至少通过一次,求最少需要花费的时间。

        思路:首先求出各个通道之间的距离,题目变成如上所述的一个问题。用二进制描述状态,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[N][N];int dp[N][35000],mark[N][N],vis[N][N],st[N];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[N];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;}


0 0
原创粉丝点击