原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4640

解题思路:

首先用一个简单的2^n*n的dp可以求出一个人访问一个给定状态的最小花费,因为这i个人是等价的,所以用dp[i][mask]表示i个人跑完mask这个状态的最小花费,所以首先枚举集合mask,对于dp[i][mask],枚举mask的子集v,dp[i][mask]可以由dp[1][v],dp[i-1][mask^v]转移过来,注意这里用来合并的集合是不能有重复的,这个类似背包……这样就可以算出对于每个状态三个人访问完的最小花费,之后对于给定的需要访问的状态,枚举包含这个给定状态的集合更新答案就可以了……注意对于刚开始给定的图是不能floyd的,因为要求任意两个人的路径不能相交……还有就是1这个节点可以每个人经过多次,这里需要特殊处理一下……

以上摘自杭电的解题报告

下面是我还未写完的代码,我还不会做这个题,所以···还得想想····以后会改好的

 #include <cstdio>
#include <queue>
using namespace std;
#define N (1<<17)+5
#define INF 100000000
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b int n,status; //人数,学妹位置的状态
int d[N][],dp1[N],dp2[N];
bool in[N][];
int edge[][];
queue<int> qu;
void initScan()
{
int m;
scanf("%d%d",&n,&m);
for(int i=; i<n; ++i)
{
for(int j=; j<n; ++j)
{
if(i == j) edge[i][j] = ;
else edge[i][j] = INF;
}
}
while(m--)
{
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
--u,--v;
edge[u][v] = min(edge[u][v],c);
edge[v][u] = edge[u][v];
}
int k;
status = ;
scanf("%d",&k);
while(k--)
{
int sis;
scanf("%d",&sis);
status |= (<<(sis-));
}
status >>= ;
}
void bfs()
{
memset(in,,sizeof(in));
memset(d,0x3f,sizeof(d));
qu.push();//先城市
qu.push();//后状态
d[][] = ;
in[][] = true;
while(!qu.empty())
{
int i = qu.front();//状态
qu.pop();
int j = qu.front();//城市
qu.pop();
in[i][j] = false;
for(int k=; k<n; ++k)
{
int w = i |( << k);
if(d[w][k] > d[i][j] + edge[j][k] )
{
d[w][k] = d[i][j] + edge[j][k];
if(!d[w][k])
{
qu.push(k);
qu.push(w);
in[w][k] = ;
}
}
}
}
}
void DP1()
{
memset(dp1,0x3f,sizeof(dp1));
for(int i=; i<(<<n); ++i)
{
for(int j=; j<n; ++j)
dp1[i>>] = min(dp1[i>>],d[i][j]);
}
}
void DP2()
{
for(int i=; i<(<<n); ++i)
{
int j = i;
while(j)
{
j=(j-)&i;
dp2[i] = min( dp2[i],max(dp2[j],dp2[i^j]) );
}
}
}
int solve()
{
int ans = INF;
int j = status;
while(j)
{
j=(j-)&status;
ans = min( ans,max(dp2[j],dp1[status^j]) );
ans = min(ans,max(dp2[status^j],dp1[j]) );
}
return ans;
} int main()
{
freopen("in.cpp","r",stdin);
freopen("myout.cpp","w",stdout);
int t;
scanf("%d",&t);
for(int ser=; ser<=t; ++ser)
{
initScan();
bfs();
DP1();
for(int i=; i<(<<n); ++i)
printf("d[%d] = %d\n",i,dp1[i]);
DP2();
int ans = solve();
printf("Case %d: ",ser);
if(ans == INF) printf("-1\n");
else printf("%d\n",ans);
}
return ;
}

下面是标程1:

 #include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
#define N 101
int sta;
int d[N][N];
int dp[ << ][];
bool in[ << ][];
int dp_1[ << ], dp_2[ << ];
int main() {
int t, cas = ;
scanf(" %d", &t);
while (t--) {
int n, m;
scanf(" %d %d", &n, &m);
// if(cas==13) printf("%d %d\n",n,m);
memset(d, 0x3f, sizeof(d));
for (int i = ; i < m; i++) {
int x, y, s;
scanf(" %d %d %d", &x, &y, &s);
// if(cas==13) printf("%d %d %d\n",x,y,s);
d[x][y] = min(d[x][y], s);
d[y][x] = d[x][y];
} queue<int> qu;
qu.push();
qu.push();
memset(in, , sizeof(in));
memset(dp, 0x3f, sizeof(dp));
dp[][] = ;
in[][] = true; while (!qu.empty()) {
int s_sta = qu.front();
qu.pop();
int s = qu.front() + ;
qu.pop();
in[s_sta][s - ] = false; for (int i = ; i < n; i++) {
int to = i + ;
int t_sta = ( << i) | s_sta;
if (to == )
continue;
if (dp[t_sta][to - ] > dp[s_sta][s - ] + d[s][to]) {
dp[t_sta][to - ] = dp[s_sta][s - ] + d[s][to];
if (!in[t_sta][to - ]) {
in[t_sta][to - ] = ;
qu.push(t_sta);
qu.push(to - );
}
}
}
} memset(dp_1, 0x3f, sizeof(dp_1));
for (int i = ; i < ( << n); i++) {
for (int j = ; j < n; j++) {
dp_1[i >> ] = min(dp_1[i >> ], dp[i][j]);
}
} int tar = , k;
scanf(" %d", &k);
// if(cas==13) printf("%d\n",k);
while (k--) {
int x;
scanf(" %d", &x);
// if(cas==13) printf("%d ",x);
tar |= ( << (x - ));
}
int ans = INF;
int tol = ( << (n - )) - ;
memcpy(dp_2, dp_1, sizeof(dp_1));
for (int i = ; i < ( << (n - )); i++) {
for (int j = i; j; j = (j - ) & i) {
dp_2[i] = min(dp_2[i], max(dp_1[j], dp_1[i ^ j]));
}
}
for (int i = tol; i; i--) {
for (int j = i;; j = (j - ) & i) {
if ((i & tar) == tar) {
ans = min(ans, max(dp_1[j], dp_2[i ^ j]));
}
if (j == )
break;
}
}
if (ans == INF)
ans = -;
printf("Case %d: %d\n", cas++, ans);
}
return ;
}

标程2:

 #include<stdio.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef __int64 lld;
#define pb push_back
#define mp make_pair
#define X first
#define Y second
#define maxn 20
struct Edge
{
int v,s,next;
}edge[];
int head[maxn];
int pos;
void insert(int x,int y,int s)
{
edge[pos].v=y;
edge[pos].s=s;
edge[pos].next=head[x];
head[x]=pos++;
}
int dis[<<][];
bool vis[<<][];
pair<int,int>queue[];
int rear,front;
int maxQ=;
int dp[<<];
int f[<<];
int main()
{
// freopen("input.txt","r",stdin);
int cas;
scanf("%d",&cas);
for(int cc=;cc<=cas;cc++)
{
int n,m;
scanf("%d %d",&n,&m);
memset(head,,sizeof(head));
pos=;
while(m--)
{
int x,y,s;
scanf("%d %d %d",&x,&y,&s);
insert(x,y,s);
insert(y,x,s);
}
memset(dis,-,sizeof(dis));
memset(vis,false,sizeof(vis));
rear=front=;
for(int i=head[];i;i=edge[i].next)
{
int v=edge[i].v;
v-=;
if(dis[<<v][v] == - || edge[i].s < dis[<<v][v])
{
dis[<<v][v]=edge[i].s;
if(!vis[<<v][v])
{
vis[<<v][v]=true;
queue[front++]=mp(<<v,v);
}
}
}
while(rear != front)
{
int mask=queue[rear].X;
int u=queue[rear].Y;
rear++;
if(rear == maxQ)
rear=;
vis[mask][u]=false;
for(int i=head[u+];i;i=edge[i].next)
{
int v=edge[i].v;
if(v == )
continue;
v-=;
int next=mask|(<<v);
if(dis[next][v] == - || dis[mask][u]+edge[i].s < dis[next][v])
{
dis[next][v]=dis[mask][u]+edge[i].s;
if(!vis[next][v])
{
vis[next][v]=true;
queue[front++]=mp(next,v);
if(front == maxQ)
front=;
}
}
}
}
memset(dp,-,sizeof(dp));
dp[]=;
int T=<<(n-);
for(int mask=;mask<T;mask++)
for(int i=;i<n-;i++)
{
if(dis[mask][i] == -)
continue;
if(dp[mask] == - || dis[mask][i] < dp[mask])
dp[mask]=dis[mask][i];
}
for(int mask=;mask<T;mask++)
f[mask]=dp[mask];
for(int k=;k<;k++)
{
for(int u=T-;u>;u--)
for(int v1=u;;v1=(v1-)&u)
{
int v2=u^v1;
if(dp[v1] == - || f[v2] == -)
{
if(v1 == )
break;
continue;
}
if(dp[u] == - || max(dp[v1],f[v2]) < dp[u])
dp[u]=max(dp[v1],f[v2]);
if(v1 == )
break;
}
}
int Q;
scanf("%d",&Q);
int mask=;
while(Q--)
{
int x;
scanf("%d",&x);
x-=;
mask|=<<x;
}
int ans=-;
for(int u=;u<T;u++)
if((u&mask) == mask)
{
if(dp[u] == -)
continue;
if(ans == - || dp[u] < ans)
ans=dp[u];
}
printf("Case %d: %d\n",cc,ans);
}
return ;
}

HDU 4640 状态压缩DP 未写完的更多相关文章

  1. HDU 1074 (状态压缩DP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:有N个作业(N<=15),每个作业需耗时,有一个截止期限.超期多少天就要扣多少 ...

  2. HDU 3341 状态压缩DP+AC自动机

    题目大意: 调整基因的顺序,希望使得最后得到的基因包含有最多的匹配串基因,使得所能达到的智商最高 这里很明显要用状态压缩当前AC自动机上点使用了基因的情况所能达到的最优状态 我最开始对于状态的保存是, ...

  3. hdu 4284 状态压缩dp

    题意: 有N 个点的无向图,要去其中 h个地点做事,做事需要先办理护照,之后可以挣一定数量的钱,知道了一开始有的总钱数,和 一些城市之间           道路的花费,问可不可以在 指定的 h 个城 ...

  4. hdu 2167 状态压缩dp

    /* 状态转移方程:dp[i][j]=Max(dp[i][j],dp[i-1][k]+sum[i][j]); */ #include<stdio.h> #include<string ...

  5. HDU 4856 (状态压缩DP+TSP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4856 题目大意:有一个迷宫.迷宫里有些隧道,每个隧道有起点和终点,在隧道里不耗时.出隧道就耗时,你的 ...

  6. hdu 1074(状态压缩dp+记录路径)

    题意:给了n个家庭作业,然后给了每个家庭作业的完成期限和花费的实践,如果完成时间超过了期限,那么就要扣除分数,然后让你找出一个最优方案使扣除的分数最少,当存在多种方案时,输出字典序最小的那种,因为题意 ...

  7. HDU 4906 状态压缩dp

    Our happy ending Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  8. 2016"百度之星" - 初赛(Astar Round2A)1002 / HDU 5691 状态压缩DP

    Sitting in Line Problem Description   度度熊是他同时代中最伟大的数学家,一切数字都要听命于他.现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了.游戏的规则十 ...

  9. HDU 5067 (状态压缩DP+TSP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5067 题目大意:蓝翔挖掘机挖石子.把地图上所有石子都运回起点,问最少耗时. 解题思路: 首先得YY出 ...

随机推荐

  1. Python -- Scrapy 命令行工具(command line tools)

    结合scrapy 官方文档,进行学习,并整理了部分自己学习实践的内容 Scrapy是通过 scrapy 命令行工具进行控制的. 这里我们称之为 “Scrapy tool” 以用来和子命令进行区分. 对 ...

  2. robot切换窗口

    在用robot做自动化测试的时候,经常遇到新开窗口,需要切换窗口的情况. 两种方式来解决: (1)用robot的关键字来解决 实现窗口切换的功能 @{handlelist} List Windows ...

  3. 深入理解Java中配置环境变量

    深入理解Java中配置环境变量 配置的目的: 本来只在安装JDK的bin目下能运行java.exe,javac.exe,jar.exe,javadoc.exe等Java开发工具包命令,我们现在想让在所 ...

  4. select exists 的应用一例

    当遇到多层exists的时候,事情就变得开始复杂了.我们来看看这个例子吧 假设有三张表 选课表:学号.课程号 学生表:学号.姓名 课程表:课程号.课程名 请选出选了所有课程的学生 SELECT 姓名 ...

  5. python模块——hashlib模块(简单文件摘要算法实现)

    #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = "loki" # Usage: hashlib模块 import ...

  6. UVA-11029 Leading and Trailing

    Apart from the novice programmers, all others know that you can’t exactly represent numbers raised t ...

  7. Activiti工作流笔记(1)

    Activiti下载地址: eclipse的activiti插件下载地址:http://www.activiti.org/designer/archived/activiti-designer-5.1 ...

  8. 转载:移动端+微信小程序实现,手机端滑动分页代码思路(ajax)

    //一般在PC上我们要分页都是通过上一页和下一页来实现的,手机通过当下滑到一定程度的时候自动加载下一页面//实现思路:首先加载部分数据,当下滑到某个元素可见的时候,如果还有数据,则新发送请求,然后追加 ...

  9. jenkins的应用与搭建

    实验条件2个服务器, git服务器 ip地址:192.168.200.151 Jenkins服务器 ip地址:192.168.200.132 操作系统:centos7.5 [root@git ~]# ...

  10. vuex 简单理解

    废话不多说,直接上图!                 不懂的 参考 API