poj 2197 hoj 2027 Jill's Tour Paths 搜索

题意就是一个人去旅游,不能重复经过同一个城市,且走的路的距离有限制,求所有符合条件的能从起点走到终点的路径,按照距离从小到大输出,如果距离相等,就按照路径的字典升序输出

这题主要麻烦在输出上,得有路径,而且还得各种顺序……我分别用深搜和广搜做了这题,不过广搜写残了,效率和空间远不及深搜

深搜的时候,保存当前的路长和路径信息,不断往下找,注意剪枝,就是长度超过限制,搜到重点之后先把结果放进vector;深搜结束后再写个快排的cmp就搞定了

广搜的话得用状态压缩,用一个变量记录当前状态下已经经过的城市,结果的处理和深搜类似


深搜代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int b[25];
int map[25][25];
int a[25][25];
int st,en;
int n,m;
int len,cnt;
struct point
{
    int path[25];
    int length;
};
bool vis[25];
vector<point> v;
void dfs(int x,point p,int l)
{
    if(x==en)
    {
        v.push_back(p);
        return;
    }
    for(int i=1; i<=a[x][0]; i++)
    if(!vis[a[x][i]]&&l+map[x][a[x][i]]<=len)
    {
        vis[a[x][i]] = 1;
        p.length+=map[x][a[x][i]];
        p.path[++p.path[0]] = a[x][i];
        dfs(a[x][i],p,l+map[x][a[x][i]]);
        p.path[0]--;
        p.length-=map[x][a[x][i]];
        vis[a[x][i]] = 0;
    }
}
int cmp(const point &a,const point b)
{
    if(a.length==b.length)
    {
        for(int i=1; i<=a.path[0]&&i<=b.path[0]; i++)
        if(a.path[i]==b.path[i]) continue;
        else return a.path[i]<b.path[i];
    }
    return a.length<b.length;
}
int main()
{
    int cas = 0;
    while(scanf("%d",&n)&&n>0)
    {
        scanf("%d",&m);
        memset(map,0,sizeof(map));
        memset(a,0,sizeof(a));
        while(m--)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            map[x][y] = map[y][x] = z;
            a[x][++a[x][0]] = y;
            a[y][++a[y][0]] = x;
        }
        scanf("%d%d",&st,&en);
        scanf("%d",&len);
        point p;
        p.length = 0;
        p.path[0] = 1;
        p.path[1] = 1;
        memset(vis,0,sizeof(vis));
        vis[1] = 1;
        dfs(1,p,0);
        if(cas) puts("");
        printf("Case %d:\n",++cas);
        int size = v.size();
        if(size==0)
        {
            printf(" NO ACCEPTABLE TOURS\n");
            continue;
        }
        sort(v.begin(),v.end(),cmp);
        for(int i=0; i<size; i++)
        {
            point tmp = v[i];
            printf(" %d:",tmp.length);
            for(int j=1; j<=tmp.path[0]; j++)
            printf(" %d",tmp.path[j]);
            puts("");
        }
        v.clear();
    }
    return 0;
}

广搜代码(这个写的很残,懒得管了):

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int b[25];
int map[25][25];
int a[25][25];
struct point
{
    int x,k;
    int dis;
    int fa;
    point()
    {
        k = 0;
        fa = 0;
        dis = 0;
    }
};
point q[1000010];
int ans[1000010];
int st,en;
int cnt0;
void dfs(int x[25],int k)
{
    if(q[k].x==st)
    {
        x[cnt0++] = st;
        return;
    }
    dfs(x,q[k].fa);
    x[cnt0++] = q[k].x;
}
int cmp(const int &a,const int &b)
{
    if(q[a].dis==q[b].dis)
    {

        int x[25];
        memset(x,0x7f,sizeof(x));
        cnt0 = 0;
        dfs(x,a);
        int cnt1 = cnt0;
        cnt0 = 0;
        int y[25];
        memset(y,0x7f,sizeof(y));
        dfs(y,b);
        int cnt2 = cnt0;
        for(int i=0; i<cnt1||i<cnt2; i++)
        if(x[i]==y[i])
        continue;
        else return x[i]<y[i];
    }
    return q[a].dis<q[b].dis;
}
int main()
{
    int n,m;
    b[1] = 1;
    for(int i=2; i<25; i++)
    b[i] = b[i-1]<<1;
    int cas = 0;
    while(scanf("%d",&n)&&n>0)
    {
        scanf("%d",&m);
        memset(map,0,sizeof(map));
        memset(a,0,sizeof(a));
        while(m--)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            map[x][y] = map[y][x] = z;
            a[x][++a[x][0]] = y;
            a[y][++a[y][0]] = x;
        }

        scanf("%d%d",&st,&en);
        int len;
        scanf("%d",&len);
        point p;
        p.x = st;
        p.k = b[st];
        q[0] = p;
        int head = 0,tail = 1;
        int cnt = 0;
        while(head<tail)
        {
            point p0 = q[head++];
            if(p0.x==en)
            {
                ans[cnt++] = head-1;
                continue;
            }
            for(int i=1; i<=a[p0.x][0]; i++)
            if((p0.k&b[a[p0.x][i]])==0&&p0.dis+map[p0.x][a[p0.x][i]]<=len)
            {
                point tmp;
                tmp.x = a[p0.x][i];
                tmp.dis = p0.dis+map[p0.x][a[p0.x][i]];
                tmp.k = p0.k|b[a[p0.x][i]];
                tmp.fa = head-1;
                q[tail++] = tmp;
            }
        }
        if(cas) puts("");
        printf("Case %d:\n",++cas);
        if(cnt==0)
        {
            printf(" NO ACCEPTABLE TOURS\n");
            continue;
        }
        sort(ans,ans+cnt,cmp);
        for(int i=0; i<cnt; i++)
        {
            printf(" %d:",q[ans[i]].dis);
            int x[25];
            cnt0 = 0;
            dfs(x,ans[i]);
            for(int j=0; j<cnt0; j++)
            printf(" %d",x[j]);
            puts("");
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值