洛谷P1171 售货员的难题【状压DP】
题目描述
某乡有n个村庄(1
输入格式:
村庄数n和各村之间的路程(均是整数)。
输出格式:
最短的路程。
输入样例:
3
0 2 1
1 0 2
2 1 0
输出样例
3
说明
输入解释
3 {村庄数}
0 2 1 {村庄1到各村的路程}
1 0 2 {村庄2到各村的路程}
2 1 0 {村庄3到各村的路程}
题目分析
又是一道状压DP经典
我们以一串二进制数表示村庄的集合(状态)
1表示该村庄访问过,0表示没有
定义dp[i][j]表示
从起点到第j号点
且到达时状态恰好为i的最短路
则最后答案就是min(dp[(1<< n) -1][i] + map[i][1]) (2<=i<=n)
其中map数组是题目给定的各村庄间距离
而求取dp数组的方法
我们可以借鉴Floyd的思想
具体代码:
for(int i =0;i<=(1 << n) -1;i++)
for(int j=1;j<=n;j++)
if( !( (1 << j-1) & i) )
for(int k=1;k<=n;k++)
if( ( (1 << k-1) & i) )
dp[((1 << j-1) | i)][j] = min(dp[((1 << j-1) | i)][j],dp[i][k] + map[k][j]);
如何解释呢
第一层循环 i 枚举每个可能的状态
第二层循环 j 枚举下一步到达的点
if( !( (1 << j-1) & i) ) 这句判断 j 是否已访问
1左移j-1位,则此时只有第j位是1
若状态 i 的第 j 位为1,则&与运算返回1,表示已访问,否则没访问
第三层循环枚举中介点k
if语句判断同上
接下来核心代码——更新
dp[ (1 << j-1) | i ][j] = min(dp[((1 << j-1) | i)][j],dp[i][k] + map[k][j]);
(1 << j-1) | i 将状态的第j为置为1得到下一步的状态
dp[i][k] + map[k][j])表示在当前状态i中寻找中介点检查最短路是否可以更新
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
int n;
int dp[1100010][25];
int map[25][25];
int main()
{
n=read();
for(int i = 1;i <= n;i ++)
for(int j = 1;j <= n;j ++)
map[i][j]=read();//读入个村庄间距离
memset(dp,63,sizeof(dp));
dp[1][1] = 0;//状态1表示此时只有1号点访问过
for(int i =0;i<=(1 << n) -1;i++)
for(int j=1;j<=n;j++)
if( !( (1 << j-1) & i) )
for(int k=1;k<=n;k++)
if( ( (1 << k-1) & i) )
dp[((1 << j-1) | i)][j] = min(dp[((1 << j-1) | i)][j],dp[i][k] + map[k][j]);//核心代码,解释如上所述
int ans = 2147483640;
for(int i=2;i<=n;i++)//最后从状态(1<<n)-1(二进制全为1)中寻找到1最短的点
ans=min(ans,dp[(1<<n)-1][i] + map[i][1]);
cout<<ans;
return 0;
}
蒟蒻看到这题n<=20的范围挺大
担心卡常所以开了O2
最后总共跑了1392ms,最大的点跑了608ms
目测不开O2也是能过的
洛谷P1171 售货员的难题【状压DP】的更多相关文章
- 2018.07.18 洛谷P1171 售货员的难题(状压dp)
传送门 感觉是一道经典的状压dp,随便写了一发卡了卡常数开了个O(2)" role="presentation" style="position: relati ...
- 洛谷P1171 售货员的难题
P1171 售货员的难题 题目背景 数据有更改 题目描述 某乡有n个村庄(1<n<20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且 ...
- 洛谷 P1171 售货员的难题
P1171 售货员的难题 题目背景 数据有更改 题目描述 某乡有n个村庄(1<n<20),有一个售货员,他要到各个村庄去售货,各村庄之间的路程s(0<s<1000)是已知的,且 ...
- 【题解】洛谷P3959 [NOIP2017TG] 宝藏(状压DP+DFS)
洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017时还很弱(现在也很弱 看出来是DP 但是并不会状压DP 现在看来思路并不复 ...
- codevs2596 售货员的难题(状压dp)
2596 售货员的难题 时间限制: 1 s 空间限制: 32000 KB 题目等级 : 钻石 Diamond 题目描述 Description 某乡有n个村庄(1<n<=15 ...
- 洛谷 P1278 单词游戏 【状压dp】
题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...
- 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]
题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...
- 洛谷P2761 软件补丁问题(状压DP,SPFA)
题意 描述不清... Sol 网络流24题里面怎么会有状压dp?? 真是狗血,不过还是简单吧. 直接用$f[sta]$表示当前状态为$sta$时的最小花费 转移的时候枚举一下哪一个补丁可以搞这个状态 ...
- 洛谷P2831 愤怒的小鸟——贪心?状压DP
题目:https://www.luogu.org/problemnew/show/P2831 一开始想 n^3 贪心来着: 先按 x 排个序,那么第一个不就一定要打了么? 在枚举后面某一个,和它形成一 ...
随机推荐
- python通过scapy模块进行arp断网攻击
前言: 想实现像arpsoof一样的工具 arp断网攻击原理: 通过伪造IP地址与MAC地址实现ARP欺骗,在网络发送大量ARP通信量.攻击者 只要持续不断发送arp包就能造成中间人攻击或者断网攻击. ...
- [SinGuLaRiTy] Nescafe 24杯模拟赛
[SinGularLaRiTy-1044] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 小水塘(lagoon) 题目描述 忘川沧月的小水塘 ...
- Socket与ServerSocket
ServerSocket: 用于打开服务端口,等待客户端连接,运行在服务端. Socket: 用于连接指定服务器的指定端口,运行在客户端. flush是输出到缓冲区,缓冲区没满的话不发送,close的 ...
- 全新的软件项目,好的开始决定了成功一半!(需求&计划)
刚看完“无问西东”,电影里说人总归还是要留下些足迹(文字)的,那么赶紧跑图书馆来留下些文字. 最近去瑞士启动了一个新的项目,那么早上做项目,晚上总结留下了一张张思维导图来记录当时的感受, 手稿如下,字 ...
- centos7 安装jdk 1.8
1.下载jdk1.8 for linux的安装包 jdk-8u11-linux-x64.tar.gz,下载地址:http://download.oracle.com/otn-pub/java/jdk ...
- ClearCase config_spec
1.使用分支前要在vob创建branch type,Config_Spec不能自动创建branch type: 2.如果可能,最好在以前确定的label上进行新的工作,避免维护复杂的config_s ...
- jsp的语法
JSP指令和脚本元素指令 <%@ 指令%>声明 <%! 声明%>表达式 <%= 表达式%>代码段/脚本段 <% 代码段%>注释 <%-- 注释-- ...
- python 调用 R,使用rpy2
python 与 R 是当今数据分析的两大主流语言.作为一个统计系的学生,我最早接触的是R,后来才接触的python.python是通用编程语言,科学计算.数据分析是其重要的组成部分,但并非全部:而R ...
- python脚本检查TCP端口是否正常
#!/usr/bin/python import socket import re import sys def check_server(address,port): s = socket.sock ...
- R语言的神奇之基于向量
对于大多数需要来说,当我们需要计算两个向量相加时,我们需要分别对这两个向量的元素进行遍历,所以写起来非常的麻烦.下面看看R语言是如何实现的. 首先,将1:5赋予一个名为x的向量 > X<- ...