LightOJ - 1316 A Wedding Party(最短路+状态压缩)
2015-11-10 21:08
330 查看
题目大意:有N个点,M条有向边,S个特殊点。现在要求你从0走到N-1,经过的特殊点的数量最多,且走过的路径最小
解题思路:刚开始开了一个dp
[1 << S]的数组,可想而知,MLE了
后面想想,只需要处理出(开始点,特殊点,终点)这些点之间的距离,再用状态压缩去做就好了
解题思路:刚开始开了一个dp
[1 << S]的数组,可想而知,MLE了
后面想想,只需要处理出(开始点,特殊点,终点)这些点之间的距离,再用状态压缩去做就好了
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int M = 10010; const int N = 510; const int S = (1 << 15) + 10; const int INF = 0x3f3f3f3f; struct Edge{ int u, v, dis, next; Edge() {} Edge(int u, int v, int dis, int next): u(u), v(v), dis(dis), next(next) {} }E[M]; struct Node { int u, dis; Node() {} Node(int u, int dis): u(u), dis(dis) {} bool operator < (const Node &a) const { return dis > a.dis; } }; struct DP{ int pos, statu; DP() {} DP(int pos, int statu): pos(pos), statu(statu) {} }; int head , dis[20] , shop[20], dp[20][S]; bool vis , start_shop; int n, m, s, cas = 1; void init() { memset(head, -1, sizeof(head)); scanf("%d%d%d", &n, &m, &s); int u, v, dis; start_shop = false; for (int i = 0; i < s; i++) { scanf("%d", &shop[i]); if (shop[i] == 0) start_shop = true; } sort(shop, shop + s); for (int i = 0; i < m; i++) { scanf("%d%d%d", &u, &v, &dis); E[i] = Edge(u, v, dis, head[u]); head[u] = i; } } void dijkstra(int s, int *d) { for (int i = 0; i < n; i++) d[i] = INF; memset(vis, 0, sizeof(vis)); priority_queue<Node> Q; d[s] = 0; Q.push(Node(s, 0)); while (!Q.empty()) { int u = Q.top().u; Q.pop(); if (vis[u]) continue; vis[u] = true; for (int i = head[u]; ~i; i = E[i].next) { int v = E[i].v; if (d[v] > d[u] + E[i].dis) { d[v] = d[u] + E[i].dis; Q.push(Node(v, d[v])); } } } } int bitcount(int x) { return x ? bitcount(x / 2) + x % 2: 0; } void solve() { dijkstra(0, dis[s]); for (int i = 0; i < s; i++) dijkstra(shop[i], dis[i]); if (dis[s][n - 1] == INF) printf("Case %d: Impossible\n", cas++); else { memset(dp, 0x3f, sizeof(dp)); queue<DP> Q; Q.push(DP(s, 0)); dp[s][0] = 0; int Max_shop = 0, Min_dis = INF; while (!Q.empty()) { int u = Q.front().pos; int statu = Q.front().statu; Q.pop(); if (dis[u][n - 1] != INF) { int t = bitcount(statu); if (t > Max_shop) { Max_shop = t; Min_dis = dis[u][n - 1] + dp[u][statu]; } else if (t == Max_shop && dp[u][statu] + dis[u][n - 1] < Min_dis) { Min_dis = dp[u][statu] + dis[u][n - 1]; } } for (int i = 0; i < s; i++) { if (shop[i] == 0 || statu & (1 << i)) continue; int sta = statu | (1 << i); if (dp[i][sta] > dp[u][statu] + dis[u][shop[i]]) { dp[i][sta] = dp[u][statu] + dis[u][shop[i]]; Q.push(DP(i, sta)); } } } Max_shop += start_shop; printf("Case %d: %d %d\n", cas++, Max_shop, Min_dis); } } int main() { int test; scanf("%d", &test); while (test--) { init(); solve(); } return 0; }
相关文章推荐
- HDU 5317 RGCDQ
- 《CSS权威指南》
- C语言第四天课堂笔记<详细+注释>
- C语言第三天课堂笔记<详细+注释>
- 关于本人在VMware安装MAC碰到的问题和解决办法
- JAVA——包装类的自动装箱和拆箱
- DDR引发的问题(上)
- POJ 1423 Big Number
- java字符串中NUL域的去除
- C语言第二天课堂笔记<详细+注释>
- POJ 1423 Big Number
- 关于Python中深拷贝与浅拷贝的理解(二)---排bug
- java 路径分隔符
- Java的学习--关于Java中String上的操作汇总
- hdu 5115 Dire Wolf
- DTCMS自定义标签:面包屑导航,栏目中通过栏目调用名称获得栏目名称
- HTML DOM(一):认识DOM
- BP神经网络原理推导
- 插入排序
- C#语言 函数