题目背景

数据有更改

题目描述

某乡有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
输出样例#1:

3

说明

输入解释

3 {村庄数}

0 2 1 {村庄1到各村的路程}

1 0 2 {村庄2到各村的路程}

2 1 0 {村庄3到各村的路程}

80分的暴力:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,tot;
int vis[];
int map[][];
int minn=0x7f7f7f7f,ans=0x7f7f7f7f;
void dfs(int now,int num,int dis){
if(num==n){
ans=min(ans,dis+map[now][]);
return ;
}
if(dis+n-num-+minn>=ans) return ;
for(int i=;i<=n;i++)
if(!vis[i]){
vis[i]=;
dfs(i,num+,dis+map[now][i]);
vis[i]=;
}
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
scanf("%d",&map[i][j]);
for(int i=;i<=n;i++)
minn=min(minn,map[i][]);
vis[]=;
dfs(,,);
cout<<ans;
}
/*
3
0 1 2
2 0 1
1 2 0
*/

正解:

状压的思路是一样的。用 f [ i ] [ j ] 来表示 i 状态下走到第 j 个地方的最小值。这里的 i 实质上是一个二进制数,每一位是 0 是 1 即表示每个地方有无去过,但是转为十进制表示状态,这便是状态压缩的基本思想。先从 3(二进制 11) 枚举 i,每次给 i 加 2(因为第一位所表示的第一个地方是起点,不管如何都去过,因此其永远是 1)。得到可能的 i 后,枚举 i 的除第一位外每个为 1 的位,并替换 1 为 0 得到能转移到状态 i 的状态 s,具体转移过程就不多说了,总之位运算什么的详见代码。

那么如何进行优化呢?下面就是几个好办法:

  • 1 . 首先如果规定 n = 5,即有售货员要去五个地方,枚举到 i = 3(二进制 00011) 时,我们不一定需要从最低位一直枚举到第 n 位,因为第 n 位可能在枚举 i 的很久以后才能变成 1,这之前都是 0,浪费时间复杂度,因此我们可以规定整数 k,表示目前可能为 1 的最高位的位数。当 i 超过 2 的 k 次方时,更新 k,即为 k 自增。这里 2 的 k 次方可以暂时用变量 p 表示,k 更新时用位运算给 p 向左移一位。

  • 2 . 尽量不用 STL 的 min,虽然好用,但是宁愿用 define 手打 QAQ,另外其他联系到位运算的,比如取某数二进制位下的某位的值,也可以用 define 而不是新建什么内联函数。

  • 3 . 对于状态 i,其由不同的状态 s 转移而来,因此,我们倒推 s 的时候,先确认其可行性,再枚举 l ,用 f [ s ] [ l ] 更新 f [ i ] [ j ] 的最小值。

个人认为第 2 点优化程度是最大的。下面给出代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define min(a,b) a<b?a:b
using namespace std;
int n,m,ans=0x7f7f7f7f;
int map[][],f[<<][];
int main(){
scanf("%d",&n);
m=(<<n)-;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
scanf("%d",&map[i][j]);
memset(f,0x7f,sizeof(f));
f[][]=;
for(int i=,k=,p=;i<=m;i+=){
if(i>p) p=p<<,k++;
for(int j=;j<=k;j++)
if((i>>j-)&){
int s=i^(<<j-);
for(int l=;l<j;l++)
f[i][j]=min(f[i][j],f[s][l]+map[l][j]);
for(int l=j+;l<=k;l++)
f[i][j]=min(f[i][j],f[s][l]+map[l][j]);
}
}
for(int i=;i<=n;i++)
ans=min(ans,f[m][i]+map[i][]);
cout<<ans;
}

洛谷 P1171 售货员的难题的更多相关文章

  1. 洛谷P1171 售货员的难题

    P1171 售货员的难题 题目背景 数据有更改 题目描述 某乡有n个村庄(1<n<20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且 ...

  2. 洛谷 P1171 售货员的难题 【状压dp】

    题目描述 某乡有n个村庄(1<n<20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且A村到B村与B村到A村的路大多不同.为了提高效率 ...

  3. 洛谷P1171 售货员的难题【状压DP】

    题目描述 某乡有n个村庄(1 输入格式: 村庄数n和各村之间的路程(均是整数). 输出格式: 最短的路程. 输入样例: 3 0 2 1 1 0 2 2 1 0 输出样例 3 说明 输入解释 3 {村庄 ...

  4. 2018.07.18 洛谷P1171 售货员的难题(状压dp)

    传送门 感觉是一道经典的状压dp,随便写了一发卡了卡常数开了个O(2)" role="presentation" style="position: relati ...

  5. P1171 售货员的难题

    P1171 售货员的难题 题目描述 某乡有nn个村庄(1<n \le 201<n≤20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)s(0< ...

  6. 洛谷 P1379 八数码难题 Label:判重&&bfs

    特别声明:紫书上抄来的代码,详见P198 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给 ...

  7. 【题解】P1171 售货员的难题

    Tags 搜索,状压​. 裸的旅行商问题 #include <stdio.h> #include <string.h> #define re register #define ...

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

    题目背景 数据有更改 题目描述 某乡有nn个村庄(1<n \le 201<n≤20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)s(0<s ...

  9. 洛谷P1379八数码难题

    题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中. 要求解的问题是:给出一种初始布局(初始状态)和目标布局(为 ...

随机推荐

  1. 关于exsi的虚拟网络

    相关术语: VM Network 默认的网络 VSwitch   (默认)标准交换机 (exsi的内核中) Port groups  (用来定义各个不同vlan) DVSwitch分布式交换机(exs ...

  2. 连类比事-category和extension

    extension看起来很像一个匿名的category,但是extension和有名字的category几乎完全是两个东西. extension在编译期决议,它就是类的一部分,在编译期和头文件里的@i ...

  3. 3ds max打造诱人三维水果教程:鸭梨_3dmax教程

    本系列我们介绍用3DsMAX打造美味诱人水果的实例,入门者可以按照步骤学习简单的造型和材质设定.之前我们介绍了苹果和桔子的绘制方法,今天我们介绍的主角是——鸭梨. 进入“创建”命令面板.选择“图形”按 ...

  4. WordPress 增加 keywords 和 description

    WordPress 增加 keywords 和 description . <?php $keywords = '798资源网'; $description = '798资源网'; //文章页 ...

  5. [Java] 使用 Apache的 Commons-net库 实现FTP操作

    因为最近工作中需要用到FTP操作,而手上又没有现成的FTP代码.就去网上找了一下,发现大家都使用Apache的 Commons-net库中的FTPClient. 但是,感觉用起来不太方便.又在网上找到 ...

  6. Echache整合Spring缓存实例讲解

    摘要:本文主要介绍了EhCache,并通过整合Spring给出了一个使用实例. 一.EhCache 介绍 EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中 ...

  7. 【转】Java集合间的相互转换

    下面代码演示了List<-->数组.List<-->Set.数组<-->Set.Map将键转化为Set.Map将值转化为Set.Map将值转化为List等集合常用转 ...

  8. POJ 3207 Ikki&#39;s Story IV - Panda&#39;s Trick(2-sat)

    POJ 3207 Ikki's Story IV - Panda's Trick id=3207" target="_blank" style=""& ...

  9. 转:百分百激活office for mac2011的激活文件

    方法:1点击finder             2点击系统盘             3点击资源库             4找到Preferences文件夹             5用压缩包里的 ...

  10. c#程序中使用&quot;like“查询access数据库查询为空的问题

    今天,在开发的过程中发现了一个特别奇怪的问题:access中like查询时候.在Access数据库中运行,发现能够查询出结果.这是在数据库上运行.select * from KPProj where ...