• FZU 2186 小明的迷宫 【压状dp】


     Problem Description

    小明误入迷宫,塞翁失马焉知非福,原来在迷宫中还藏着一些财宝,小明想获得所有的财宝并离开迷宫。因为小明还是学生,还有家庭作业要做,所以他想尽快获得所有财宝并离开迷宫。

     Input

    有多组测试数据。

    每组数据第一行给出两个正整数n,m(0<n,m<=100)。代表迷宫的长和宽。

    接着n行,每行m个整数。正数代表财宝(财宝的个数不超过10);负数代表墙,无法通过;0代表通道。

    每次移动到相邻的格子,所花费的时间是1秒。小明只能按上、下、左、右四个方向移动。

    小明的初始位置是(1,1)。迷宫的出口也在(1,1)。

     Output

    输出获得所有财宝并逃出迷宫所花费的最小时间,如果无法完成目标则输出-1。

     Sample Input

    3 3 0 0 0 0 100 0 0 0 0 2 2 1 1 1 1

     Sample Output

    4 4
     
    思路: 发现是一个中国邮递员问题,果断压状
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 const int dx[10]={0,0,0,1,-1},dy[10]={0,1,-1,0,0};
     7 int a[109][109],monx[100],mony[100],n,m,ma[109][109];
     8 queue<int>qans,qx,qy;
     9 bool visit[109][109];
    10 int check(int x,int y){
    11     if(x<=0 || x>n || y<=0 || y>m || a[x][y]<0 || visit[x][y])return 1;
    12     return 0;
    13 }
    14 void bfs(int x,int y,int sc)
    15 {
    16     memset(visit,0,sizeof(visit));
    17     int l=0,r=0;visit[x][y]=1;
    18     qx.push(x);qy.push(y);qans.push(0);
    19     while(!qx.empty())
    20     {
    21         x=qx.front();y=qy.front();
    22         qx.pop();qy.pop();
    23         int ans=qans.front();
    24         qans.pop();
    25         for(int i=1;i<=4;i++)
    26         {
    27             int xx=x+dx[i],yy=y+dy[i];
    28             if(check(xx,yy))continue;
    29             if(a[xx][yy]>0)ma[sc][a[xx][yy]]=ans+1;
    30             visit[xx][yy]=1;
    31             qx.push(xx);qy.push(yy);qans.push(ans+1);
    32         }
    33     }
    34 }
    35 int only_one(int k){
    36         if(k-(k & (-k)) == 0)return 1;return 0;
    37 }
    38 int dp[15][10000];
    39 int dfs2(int k,int s,int h)
    40 {
    41         if(dp[k][s]!=-1)return dp[k][s];
    42         if(only_one(s))return ma[k][1];
    43         int ans=0x3f3f3f3f,full = ((1<<(h))-1) ^ (1<<(k-1));
    44         for(int i=1;i<=h;i++)
    45         if(i != k && ((s & ((1<<(i-1)))) !=0))ans=min(ans,dfs2(i,s & full,h) + ma[k][i]);
    46         return dp[k][s]=ans;
    47 }
    48 int main()
    49 {
    50     while(scanf("%d%d",&n,&m)!=EOF)
    51     {
    52                 memset(dp,-1,sizeof(dp));
    53                 memset(ma,0x3f,sizeof(ma));
    54         int h=0,flag=0;
    55         for(int i=1;i<=n;i++)
    56         {
    57             for(int j=1;j<=m;j++)
    58             {
    59                 scanf("%d",&a[i][j]);
    60                 if(i==1 && j==1)flag=a[i][j];
    61                 if(a[i][j]>0 || (i==1 && j==1))a[i][j]=++h,monx[h]=i,mony[h]=j;
    62             }
    63         }
    64         for(int i=1;i<=h;i++)ma[i][i]=0;
    65         for(int i=1;i<=h;i++)bfs(monx[i],mony[i],i);
    66         if(flag<0)
    67         {
    68                         printf("-1
    ");continue;
    69         }
    70         int u=dfs2(1,(1<<h)-1,h);
    71         if(u>=0x3f3f3f3f)u=-1;
    72                 printf("%d
    ",u);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    社交需求和社交产品的更替
    腾讯产培生面经
    【C++基础】类class
    【C++基础】结构struct
    【C++基础】C-串知识整理
    GeoServer war包在tomcat7中配置遇到的一个问题
    pgrouting 2.0 的环境配置
    阿里2014年9月笔试中的一个算法设计题--擦黑板剩余数字
    VisualSVN Server的启动关闭脚本
    二叉树遍历(前序、中序、后序)的递归及非递归实现(小结)
  • 原文地址:https://www.cnblogs.com/philippica/p/4357486.html
Copyright © 2020-2023  润新知