HDU 4640 状态压缩DP 未写完
2013-08-03 21:38
288 查看
原题链接: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这个节点可以每个人经过多次,这里需要特殊处理一下……
以上摘自杭电的解题报告
下面是我还未写完的代码,我还不会做这个题,所以···还得想想····以后会改好的
View Code
解题思路:
首先用一个简单的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<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[1000010]; 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[1<<16][16]; bool vis[1<<16][16]; pair<int,int>queue[2000010]; int rear,front; int maxQ=2000010; int dp[1<<16]; int f[1<<16]; int main() { // freopen("input.txt","r",stdin); int cas; scanf("%d",&cas); for(int cc=1;cc<=cas;cc++) { int n,m; scanf("%d %d",&n,&m); memset(head,0,sizeof(head)); pos=1; while(m--) { int x,y,s; scanf("%d %d %d",&x,&y,&s); insert(x,y,s); insert(y,x,s); } memset(dis,-1,sizeof(dis)); memset(vis,false,sizeof(vis)); rear=front=0; for(int i=head[1];i;i=edge[i].next) { int v=edge[i].v; v-=2; if(dis[1<<v][v] == -1 || edge[i].s < dis[1<<v][v]) { dis[1<<v][v]=edge[i].s; if(!vis[1<<v][v]) { vis[1<<v][v]=true; queue[front++]=mp(1<<v,v); } } } while(rear != front) { int mask=queue[rear].X; int u=queue[rear].Y; rear++; if(rear == maxQ) rear=0; vis[mask][u]=false; for(int i=head[u+2];i;i=edge[i].next) { int v=edge[i].v; if(v == 1) continue; v-=2; int next=mask|(1<<v); if(dis[next][v] == -1 || 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=0; } } } } memset(dp,-1,sizeof(dp)); dp[0]=0; int T=1<<(n-1); for(int mask=1;mask<T;mask++) for(int i=0;i<n-1;i++) { if(dis[mask][i] == -1) continue; if(dp[mask] == -1 || dis[mask][i] < dp[mask]) dp[mask]=dis[mask][i]; } for(int mask=0;mask<T;mask++) f[mask]=dp[mask]; for(int k=0;k<2;k++) { for(int u=T-1;u>0;u--) for(int v1=u;;v1=(v1-1)&u) { int v2=u^v1; if(dp[v1] == -1 || f[v2] == -1) { if(v1 == 0) break; continue; } if(dp[u] == -1 || max(dp[v1],f[v2]) < dp[u]) dp[u]=max(dp[v1],f[v2]); if(v1 == 0) break; } } int Q; scanf("%d",&Q); int mask=0; while(Q--) { int x; scanf("%d",&x); x-=2; mask|=1<<x; } int ans=-1; for(int u=0;u<T;u++) if((u&mask) == mask) { if(dp[u] == -1) continue; if(ans == -1 || dp[u] < ans) ans=dp[u]; } printf("Case %d: %d\n",cc,ans); } return 0; }
View Code
相关文章推荐
- hdu 4640 Island and study-sister(状态压缩dp)
- hdu 4640 Island and study-sister(状态压缩dp)
- hdu 4640 Island and study-sister(状态压缩dp)
- hdu-4778-Gems Fight!---状态压缩dp
- hdu 4352 状态压缩+数位DP
- HDU 4284 Travel(状态压缩DP)
- hdu 4057(ac自动机+状态压缩dp)
- hdu 4568(状态压缩dp)
- hdu 1565 方格取数(1)(状态压缩dp)
- hdu 3001 Travelling (状态压缩dp,三进制!)
- hdu 1565 方格取数(1) (状态压缩DP)
- HDU 3001 Travelling(状态压缩DP)
- HDU 5045 Contest(概率dp,状态压缩,2014上海网络赛1004)
- hdu 5823 color II(状态压缩DP) ★
- hdu 3217 Health(状态压缩DP)
- hdu 1565 方格取数(1)(DP 状态压缩)
- hdu1074 状态压缩dp 记录路径
- Hdu 3811 状态压缩 DP
- hdu 4539 状态压缩DP
- hdu 4539 郑厂长系列故事——排兵布阵(状态压缩DP)