HDU 4640 状态压缩DP 未写完
原题链接: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 未写完的更多相关文章
- HDU 1074 (状态压缩DP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:有N个作业(N<=15),每个作业需耗时,有一个截止期限.超期多少天就要扣多少 ...
- HDU 3341 状态压缩DP+AC自动机
题目大意: 调整基因的顺序,希望使得最后得到的基因包含有最多的匹配串基因,使得所能达到的智商最高 这里很明显要用状态压缩当前AC自动机上点使用了基因的情况所能达到的最优状态 我最开始对于状态的保存是, ...
- hdu 4284 状态压缩dp
题意: 有N 个点的无向图,要去其中 h个地点做事,做事需要先办理护照,之后可以挣一定数量的钱,知道了一开始有的总钱数,和 一些城市之间 道路的花费,问可不可以在 指定的 h 个城 ...
- hdu 2167 状态压缩dp
/* 状态转移方程:dp[i][j]=Max(dp[i][j],dp[i-1][k]+sum[i][j]); */ #include<stdio.h> #include<string ...
- HDU 4856 (状态压缩DP+TSP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4856 题目大意:有一个迷宫.迷宫里有些隧道,每个隧道有起点和终点,在隧道里不耗时.出隧道就耗时,你的 ...
- hdu 1074(状态压缩dp+记录路径)
题意:给了n个家庭作业,然后给了每个家庭作业的完成期限和花费的实践,如果完成时间超过了期限,那么就要扣除分数,然后让你找出一个最优方案使扣除的分数最少,当存在多种方案时,输出字典序最小的那种,因为题意 ...
- HDU 4906 状态压缩dp
Our happy ending Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Other ...
- 2016"百度之星" - 初赛(Astar Round2A)1002 / HDU 5691 状态压缩DP
Sitting in Line Problem Description 度度熊是他同时代中最伟大的数学家,一切数字都要听命于他.现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了.游戏的规则十 ...
- HDU 5067 (状态压缩DP+TSP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5067 题目大意:蓝翔挖掘机挖石子.把地图上所有石子都运回起点,问最少耗时. 解题思路: 首先得YY出 ...
随机推荐
- 小橙书阅读指南(十三)——连通性算法(union-find)
上一章我大概说明了什么是图论以及无向图的基础概念,本章我们要研究一种更普遍的算法——连通性算法.它属于图论的分支,也是一种抽象算法.在深入算法之前,我们先提出一个具体的问题:假设在空间中存在N个点,我 ...
- Object.defineProperty方法 使用
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象. 语法: Object.defineProperty(obj, pr ...
- SQLSERVER 对于非dbo的表增加注释
平时我们创建表的时候总是dbo.imsi_collect_state,但是有时候为了方便管理我们可能会创建架构wifi,那么表名就是wifi.imsi_collect_state 原来增加注释的方式是 ...
- Confluence 6 配置 LDAP 连接池
当 LDAP 连接池被启用后,LDAP 目录服务器将会维护一个连接池同时当必要的时候指派他们.当一个连接关闭后,这个连接将会放回到连接池中供以后进行使用.这种设置将会有效的提高系统性能. 希望配置 L ...
- 『cs231n』视频数据处理
视频信息 和我之前的臆想不同,视频数据不仅仅是一帧一帧的图片本身,还包含个帧之间的联系,也就是还有一个时序的信息维度,包含人的动作判断之类的任务都是要依赖动作的时序信息的 视频数据处理的两种基本方法 ...
- UVA-1632 Alibaba (区间DP+滚动数组)
题目大意:在一条直线上有n件珠宝,已知每件珠宝的位置,并且第 i 件珠宝在 ti 时刻就消失,问能否将所有的珠宝收集起来?如果能,求出最短时间.搜集能瞬间完成. 题目分析:区间DP.dp(i,j,0) ...
- Oracle11g温习-第八章:归档日志
2013年4月27日 星期六 10:36 1.归档和非归档的区别 1) 归档会在日志切换时,备份历史日志,用于OLTP(在线事务处理系统),可以进行冷备份和热备份,可以实现数据库完全恢复.不完全恢复 ...
- PHP:第二章——PHP中的for语句
知识点一:for语句 语法格式: for(expr1;expr2;expr3){ //代码块; } 说明: expr1:循环开始前,无条件的执行一次,并 ...
- Python实现简单的爬虫获取某刀网的更新数据
昨天晚上无聊时,想着练习一下Python所以写了一个小爬虫获取小刀娱乐网里的更新数据 #!/usr/bin/python # coding: utf-8 import urllib.request i ...
- ORA-01034:Oracle not available
ORA-01034:Oracle not available 问题描述:ora-01034常与ora-27101同时出现,都是在登录数据库的时候报该错误 错误原因:出现ORA-01034和ORA-27 ...