题意就是一个人去旅游,不能重复经过同一个城市,且走的路的距离有限制,求所有符合条件的能从起点走到终点的路径,按照距离从小到大输出,如果距离相等,就按照路径的字典升序输出
这题主要麻烦在输出上,得有路径,而且还得各种顺序……我分别用深搜和广搜做了这题,不过广搜写残了,效率和空间远不及深搜
深搜的时候,保存当前的路长和路径信息,不断往下找,注意剪枝,就是长度超过限制,搜到重点之后先把结果放进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;
}