题目链接:点击打开链接

题意:给你一个n个点的全然图, 图中随意两个点都有直接相连的路,在某些点上能够获得某些景观的入场券,有入场券和没有入场券进入景观要等候的时间不同,有k个景观。要求从1点出发參观全然部景观后回到1的最小花费。

思路: 非常明显的状态压缩DP, 由于 k 非常小,所以能够压缩成一个整数,表示哪些景观已经參观完了。 然后还要表示出当前到了哪个点, 又由于有没有票的等候时间是不同的,所以再压缩一维表示当前有了哪些景观的票。

 所以用d[i][s1][s2]表示当前在i点,已经參观了s1表示的景观,有s2表示的票  的最小花费。

细节參见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?

(a):(b)) using namespace std; typedef long long ll; const double PI = acos(-1.0); const double eps = 1e-6; const int mod = 1000000000 + 7; const int INF = 1000000000; const int maxn = 55; const int maxk = 8; int T,n,m,k,kase=0,dist[maxn][maxn],d[maxn][1<<maxk][1<<maxk]; int u,v,c,piao[maxn],vis[maxn][1<<maxk][1<<maxk]; struct node { int p, t, ft, ni; }a[maxk]; void floyd() { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { for(int k=1;k<=n;k++) { dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]); } } } } int dp(int u, int S, int s) { int& ans = d[u][S][s]; if(u == 1 && S == ((1<<k)-1)) return 0; if(vis[u][S][s] == kase) return ans; vis[u][S][s] = kase; ans = INF; for(int i=0;i<k;i++) { if(S & (1<<i)) continue; if(s & (1<<i)) { ans = min(ans, dp(a[i].p, S|(1<<i), s|piao[a[i].p]) + a[i].ft + dist[u][a[i].p]); } else ans = min(ans, dp(a[i].p, S|(1<<i), s|piao[a[i].p]) + a[i].t + dist[u][a[i].p]); } for(int i=1;i<=n;i++) { ans = min(ans, dp(i, S, s|piao[i])+dist[u][i]); } return ans; } int main() { scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i == j) dist[i][j] = 0; else dist[i][j] = INF; } } for(int i=0;i<m;i++) { scanf("%d%d%d",&u,&v,&c); dist[u][v] = dist[v][u] = c; } floyd(); ++kase; memset(piao, 0, sizeof(piao)); int S = 0, s = 0; for(int i=0;i<k;i++) { scanf("%d%d%d%d",&a[i].p,&a[i].t,&a[i].ft,&a[i].ni); for(int j=0;j<a[i].ni;j++) { scanf("%d",&v); piao[v] |= (1<<i); if(v == 1) s |= (1<<i); } } printf("Case #%d: ",kase); printf("%d\n",dp(1, 0, s)); } return 0; }



版权声明:本文为博主原创文章,未经博主同意不得转载。

举报

  • 本文已收录于下面专栏:
  • ACM竞赛

相关文章推荐

HDU4114 Disney's FastPass(floyd+状态压缩DP)旅游问题升级(难)

Disney's FastPass Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe...

HDU 4628 Pieces(状态压缩dp)

点击打开链接 题目大意: 给一个字符串。每次能够删除一个可不连续回文子串,问最少删几次能够所有删完。 思路: 由于字符串长度最大16。所以可用二进制状态表示, 1表示选取这个字符,0不选,组成一个子串。 先预处理出全部状态,看这个状态是不是

HDU 1565 方格取数(1)(插头DP||状态压缩)

Problem Description 给你一个n*n的格子的棋盘。每一个格子里面有一个非负数。 从中取出若干个数,使得随意的两个数所在的格子没有公共边。就是说所取的数所在的2个格子不能相邻,并...

HDU4539+状态压缩DP

状态压缩DP 对于某一行的状态能够由前面的两行推出。

即:dp[ i ][ j ][ k ] = max( dp[ i ][ j ][ k ] , dp[ i-1 ][ k ] [ k2 ] + ones[ j ] ); 当中i-1表示前1行。k2是前2行的状态。

/* 题意:n行m列的矩阵,1表示能够放东西,0表示不能够。曼哈顿距离为2的两个位置最多仅仅能有一个位置放东西。 问最多放多少个东西。 */ #include&lt;stdio.h&gt; #inc

HDU4628+状态压缩DP

状态压缩DP题意:每次能够去掉一个回文串。求最少几步能取完。 /* 状态压缩DP 题意:每次能够去掉一个回文串,求最少几步能取完。 */ #include&lt;stdio.h&gt; #include&lt;string.h&gt; #include&lt;stdlib.h&gt; #include&lt;algorithm&gt; #include&lt;iostream&gt; #include&lt;queue&gt; #include&lt;map&gt; #include&lt

HDU 3001 Travelling (状态压缩DP +TSP问题)

Problem Description After coding so many days,Mr Acmer wants to have a good rest.So travelling is...

hdu 1074 Doing Homework (状态压缩DP)

  连接:http://acm.hdu.edu.cn/showproblem.php?pid=1074   <h1 style="color: #1a5cc8; text-align: center; font-

hdu Disney's FastPass(状态压缩dp)

这样的题我一直喜欢用bfs搞的,可是这个题不太好bfs,主要是我刚開始想的是通过边进行状态转移,这样非常不好写。。

。于是就坑爹了。调了非常久sample都没出。。。 于是学习了一下别人的思想。

。。

通过“目的...

HDU 1074 状态DP

Problem Description <div class="panel_content" style="height: auto; margin: 0px; padding: 0

hdu 1074 状态压缩DP 贪心错的原因(D)

题目链接: 贪心可以算出正确的分数,可是不一定能得到正确的字典序。 由于贪心的时候根本没有考虑字典序。 可是假设遇到相似题目仅仅要求最小扣分,那么一定要用贪心。由于这题仅仅有15门课,假设课多枚举状态dp...
  • 微博
    微信
    QQ
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多仅仅同意输入30个字)

posted on 2017-08-12 09:25  yutingliuyl  阅读(146)  评论(0编辑  收藏  举报