FDU--- (bfs+dfs 未完待补充)

D - 小明的迷宫
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

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

Input

有多组测试数据。

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

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

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

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

Output

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

Sample Input

3 30 0 00 100 00 0 02 21 11 1

Sample Output

44

求解旅行商(TSP)问题,一般有三个方法,dp,或者回溯或者什么分之限界啥啥的,不太懂,参考了下别人的方法,其他的方法以后再说,回溯的方法是,先求出各个宝藏(加上起点)间的最短路,因为最多10个宝藏,再用次DFS回溯更新出从起点开始遍历过且仅遍历一次的最小路径。

代码:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<set>
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxd=100+5;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1 | 1
typedef long long ll;
typedef pair<int,int> pii;
//---------------------------
int dx[]= {0,0,1,-1};
int dy[]= {1,-1,0,0};
typedef struct node
{
    int x,y,t;
    node(int x_ = 0, int y_ = 0, int t_ = 0)
    {
        x = x_;
        y = y_;
        t = t_;
    }
};
int mz[maxd][maxd],vis[maxd][maxd]= {0},path[20][20];
int vist[20];
int cnt,ans,n,m;
vector<node> gold;

void init()
{
    cnt=0;
    ans=INF;
    gold.clear();
    node tmp(1,1,0);
    gold.push_back(tmp);

    for(int i=1; i<=n; ++i)
        for(int j=1; j<=m; ++j)
        {
            scanf("%d",&mz[i][j]);
            if(mz[i][j]>0 && !(i==1 && j==1))
            {
                ++cnt;
                node tmp(i,j,0);
                gold.push_back(tmp);
            }
        }
  //cout<<"gold="<<gold.size()<<endl;
  cnt=gold.size();
    for(int i=0; i<cnt; ++i)
        for(int j=0; j<cnt; ++j)
            path[i][j]=0;
}

bool ok(int x,int y)
{
    if(x<=0 || y<=0 || x>n || y>m) return false;
    return true;
}

int bfs(node a,node b)
{
    vis[a.x][a.y]=1;
    queue<node> q;
    q.push(a);
    while(!q.empty())
    {
        node now=q.front();
        q.pop();
        if(now.x==b.x && now.y==b.y)
        {
            return now.t;
        }

        for(int i=0; i<4; ++i)
        {
            int xx=now.x+dx[i];
            int yy=now.y+dy[i];
            int tt=now.t+1;
            if(ok(xx,yy) && vis[xx][yy]==0 && mz[xx][yy]>=0)
            {
                vis[xx][yy]=1;
                node tmp(xx,yy,tt);
                q.push(tmp);
            }
        }
    }
    return -1;
}

void dfs(int x,int tmpcnt,int t)
{
    if(t>ans) return;
    if(tmpcnt==cnt && path[x][0]!=-1)
    {
        ans=min(ans,t+path[x][0]);
        return;
    }

    for(int i=0; i<cnt; ++i)
    {
        //cout<<i<<endl;
        if(vist[i]==0 && path[x][i]!=-1)
        {
            vist[i]=1;
          //  cout<<"vist1="<<i<<endl;
            dfs(i,tmpcnt+1,path[x][i]+t);
          //  cout<<"vist2="<<i<<endl;
            vist[i]=0;
        }
    }
}

int main()
{
    freopen("1.txt","r",stdin);
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(int i=0; i<cnt; ++i)
            for(int j=i+1; j<cnt; ++j)
            {
                mem(vis,0);
                path[i][j]=path[j][i]=bfs(gold[i],gold[j]);

            }
//          for(int i=0; i<cnt; ++i)
//            for(int j=i+1; j<cnt; ++j)
//                cout<<i<<' '<<j<<' '<<path[i][j]<<endl;
//            cout<<endl;

        mem(vist,0);
        dfs(0,0,0);
        if(mz[1][1]<0) {printf("-1\n");continue;}
        if(ans==INF)
            printf("-1\n");
        else
            printf("%d\n",ans);

    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值