P1171 售货员的难题--搜索(剪枝)

题目背景

数据有更改

题目描述

某乡有nn个村庄(1<n \le 201<n≤20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)s(0<s<1000)是已知的,且AA村到BB村与BB村到AA村的路大多不同。为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为11,他不知道选择什么样的路线才能使所走的路程最短。请你帮他选择一条最短的路。

输入输出格式

输入格式:

村庄数nn和各村之间的路程(均是整数)。

输出格式:

最短的路程。

输入输出样例

输入样例#1: 复制

3
0 2 1
1 0 2
2 1 0

输出样例#1: 复制

3

------------------------------------------------------------
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct pd
{
    int ha,e;
}lxy[25][25];
//存图,ha表示各点时间消耗,e表示要去的点,因为排序动列,不动行,所以记下列,就是要去的点
int hrb[25],n,i,j,k,minn=1e9,maxn=1001,emm[25];//新增一个emm数组解决排序动列的问题
int cmp(pd a,pd b)
{
    return a.ha<b.ha;
}//排序函数
int ss(int x,int y,int z) //y记录走过的村庄数
{
    if(z>=minn)
        return 0;//用sort优化,提前找出最小值,剪枝
    if(z+n-y+1+maxn>=minn)//两地之间距离最短是1
        return 0;
    //预见性剪枝,maxn表示x点到1的最小距离,然后剩余点取最小值1,极值判定
    if(y==n)
    {
        minn=min(minn,z+emm[x]);
        return 0;
    }
    if(y<n)
    for(int i=2;i<=n;i++)
    if(hrb[lxy[x][i].e]==0)
    //判断是否走过,为啥是lxy[x][i].e,请见上面解释
    {
        if(z+lxy[x][i].ha+n-y+maxn>minn)
            return 0;
        //预见性剪枝,极值判定,用这两个可以90分
        hrb[lxy[x][i].e]=1;
        ss(lxy[x][i].e,y+1,z+lxy[x][i].ha);
        hrb[lxy[x][i].e]=0;
    }
    return 0;
}
int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        for(k=1;k<=n;k++)
        {
            scanf("%d",&lxy[i][k].ha);
            lxy[i][k].e=k;//记录列数
            if(i!=1&&k==1)
            maxn=min(maxn,lxy[i][1].ha),emm[i]=lxy[i][1].ha;
 //求x到1的最小时间花费,用于预见性剪枝,和存x到1的花费用于搜索结算,解决排序造成的列乱序的情况
        }
        sort(lxy[i]+1,lxy[i]+n+1,cmp);
        //STL大法好,二维数组的排序要用for,sort可以优化找出的答案minn,减少无用功
    }
    hrb[1]=1;//跑过了就要踩,不然会跑回去,想想80分代码为啥不用赋值为1?因为80分列没乱序
    ss(1,1,0);
    printf("%d",minn);
    return 0;
}

这道题吧

标签上是搜索

然而

大部分都是状压dp

但还好

还有写搜索的

(我坚持写搜索的原因就是我搜索不太好)

虽然草草的写了一个

还过了样例

但全wa了

庆幸了一小下

没有tle mle什么的

但当我不太会改的时候

才知道我的搜索是totally错的

向现实低头的我

有卑微看题解了

(题解都在代码中)

原文地址:https://www.cnblogs.com/darlingroot/p/10346901.html

时间: 2024-07-31 18:09:03

P1171 售货员的难题--搜索(剪枝)的相关文章

P1171 售货员的难题 - 状压DP【最短Hamilton路径】

P1171 售货员的难题 Sol: 最短Hamilton路径,经典的NPC问题,小数据可以通过状压DP 实现. 状态:\(f[i][j]\)表示当前在第i号点,且已经过的点的状态为j 时的最短Hamilton路径. 阶段:若以点为阶段,由于会从点i转移到点i+1,还可能从i+1转移到i-1,不具有无后效性,因此我们考虑以二进制状态为阶段进行转移. 决策:考虑由哪一个点转移而来. 转移:\(f[i][j]=\max \limits_{i\&(1<<i)\&\&i\&

【题解】P1171 售货员的难题

Tags 搜索,状压?. 裸的旅行商问题 #include <stdio.h> #include <string.h> #define re register #define GC getchar() #define Clean(X,K) memset(X,K,sizeof(X)) #define U unsigned #define Min(X,Y) (X<Y?X:Y) short Qread () { short X = 0 ; char C = GC ; while (

P1171 售货员的难题 喻队状压 DP

题目描述 某乡有n个村庄(1<n<20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同.为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短.请你帮他选择一条最短的路. 输入输出格式 输入格式: 村庄数n和各村之间的路程(均是整数). 输出格式: 最短的路程. 输入输出样例 输入样例#1: 3 0 2 1 1 0 2 2 1 0

P1171 售货员的难题 暴力dp

题面 著名的TSP问题,NPC问题 对于数据大的情况,我们可以使用一系列近似算法进行寻找解. 对于数据规模小的情况,我们可以直接暴力dp 一开始写了一个dfs,然后就被n=20的数据卡爆了 #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using std::min; const int maxn=22; int f[1<<maxn][maxn];

2596 售货员的难题

2596 售货员的难题 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 某乡有n个村庄(1<n<=15),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同.为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短.请你帮他选择一条最短的路. 输入描述 Inpu

codevs2596 售货员的难题(状压dp)

2596 售货员的难题 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 钻石 Diamond 题目描述 Description 某乡有n个村庄(1<n<=15),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同.为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短.请你帮他选择一条最短的路. 输入描述 Input D

2596 售货员的难题 水深搜

2596 售货员的难题 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 钻石 Diamond 题目描述 Description 某乡有n个村庄(1<n<=15),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同.为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为1,他不知道选择什么样的路线才能使所走的路程最短.请你帮他选择一条最短的路. 输入描述 Input D

售货员的难题

Description 某乡有n个村庄(1< n < 20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0 < s < 1000)是已知的,且A村到B村与B村到A村的路大多不同.为了提高效率,他从商店出发到每个村庄一次,然后返回商店所在的村,假设商店所在的村庄为 1,他不知道选择什么样的路线才能使所走的路程最短.请你帮他选择一条最短的路. Input 村庄数n和各村之间的路程(均是整数). Output 最短的路程 Sample Input 3 {村庄数} 0 2 1

【搜索剪枝】HDU 5469 Antonidas

通道 题意:给出1字母树,询问一字符串是否出现在该树中 思路:直接搜索剪枝,有人点分治?写了几发都T了..有人会了教我? 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct Edge { int v, nxt; Edge () { } Edge (int _v, int _n) { v = _v, nxt = _n; } }; const in