BZOJ 1097 [POI2007]旅游景点atr
来源:互联网 发布:一起走软件登录 编辑:程序博客网 时间:2024/04/26 02:50
题意:FGD想从成都去上海旅游。在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情。经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个城市登山,而是希望去另外什么地方喝下午茶。幸运的是,FGD的旅程不是既定的,他可以在某些旅行方案之间进行选择。由于FGD非常讨厌乘车的颠簸,他希望在满足他的要求的情况下,旅行的距离尽量短,这样他就有足够的精力来欣赏风景或者是泡MM了^_^. 整个城市交通网络包含N个城市以及城市与城市之间的双向道路M条。城市自1至N依次编号,道路亦然。没有从某个城市直接到它自己的道路,两个城市之间最多只有一条道路直接相连,但可以有多条连接两个城市的路径。任意两条道路如果相遇,则相遇点也必然是这N个城市之一,在中途,由于修建了立交桥和下穿隧道,道路是不会相交的。每条道路都有一个固定长度。在中途,FGD想要经过K(K<=N-2)个城市。成都编号为1,上海编号为N,而FGD想要经过的N个城市编号依次为2,3,…,K+1. 举例来说,假设交通网络如下图。FGD想要经过城市2,3,4,5,并且在2停留的时候在3之前,而在4,5停留的时候在3之后。那么最短的旅行方案是1-2-4-3-4-5-8,总长度为19。注意FGD为了从城市2到城市4可以路过城市3,但不在城市3停留。这样就不违反FGD的要求了。并且由于FGD想要走最短的路径,因此这个方案正是FGD需要的。
我们注意到K非常小,所以需要经过的城市可以状压起来,预处理出每对必须经过的城市之间的最短路,之后由小的状态向大的状态转移就好了,这题常数卡得比较紧,最短路尽量写heap+dijkstra,并且DP时判掉冗余状态,就能过了
#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<vector>#include<queue>using namespace std;const int maxn=20000+10;const int maxm=1<<21;int d[maxn],dis[23][maxm],n,m,k,f[23][23],pre[maxn],id[maxn],vis[maxn];bool inq[23][maxm];struct node{ int to,cost;};struct arr{ int p,s;};struct vv{ int p,v; bool operator <(const vv g)const { return v>g.v; }};priority_queue<vv> Q;vector<node> g[maxn];void dijkstra(int p){ memset(vis,0,sizeof(vis)); memset(d,127/2,sizeof(d)); d[id[p]]=0;Q.push((vv){id[p],d[id[p]]}); while(!Q.empty()) { vv x=Q.top();Q.pop();if(vis[x.p]) continue; vis[x.p]=1; for(int i=0;i<g[x.p].size();i++) { node e=g[x.p][i];int v=e.to; if(d[v]>d[x.p]+e.cost) { d[v]=d[x.p]+e.cost; Q.push((vv){v,d[v]}); } } } for(int i=1;i<=k+1;i++) f[p][i]=d[i]; f[p][k+2]=d[n];}void spfa(int p){ memset(d,127/2,sizeof(d)); d[id[p]]=0;queue<int> Q;Q.push(id[p]);inq[p][id[p]]=1; while(!Q.empty()) { int x=Q.front();Q.pop();inq[p][x]=0; for(int i=0;i<g[x].size();i++) { node e=g[x][i];int v=e.to; if(d[v]>d[x]+e.cost) { d[v]=d[x]+e.cost; if(!inq[p][v]) { inq[p][v]=1; Q.push(v); } } } } for(int i=1;i<=k+1;i++) f[p][i]=d[i]; f[p][k+2]=d[n];}void dp(){ memset(inq,0,sizeof(inq));queue<arr> Q; memset(dis,127/2,sizeof(dis));dis[1][0]=0; for(int s=0;s<(1<<k);s++) for(int x=1;x<=k+2;x++) for(int i=1;i<=k+2;i++) if((pre[id[i]]&s)==pre[id[i]]&&i!=x) { int ns=s; if(i>1&&i<=k+1) ns=s|(1<<(i-2)); if(dis[i][ns]>dis[x][s]+f[x][i]) dis[i][ns]=dis[x][s]+f[x][i]; }} int main(){ //freopen("1097.in","r",stdin); //freopen("1097.out","w",stdout); scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=m;i++) { int u,v,c;scanf("%d%d%d",&u,&v,&c); g[u].push_back((node){v,c}); g[v].push_back((node){u,c}); } for(int i=1;i<=k+1;i++) id[i]=i; id[k+2]=n; for(int i=1;i<=k+2;i++) dijkstra(i); int l;scanf("%d",&l); for(int i=1;i<=l;i++) { int x,y;scanf("%d%d",&x,&y); if(x<n) pre[y]+=1<<(x-2); else pre[y]+=1<<(k+1); } dp(); printf("%d\n",dis[k+2][(1<<k)-1]); return 0;}
- BZOJ 1097 [POI2007]旅游景点atr
- 【BZOJ 1097】 [POI2007]旅游景点atr
- [BZOJ]1097: [POI2007]旅游景点atr
- BZOJ 1097 POI2007 旅游景点atr SPFA+状压DP
- BZOJ 1097 [POI2007]旅游景点atr dijikstra+状压DP
- bzoj 1097: [POI2007]旅游景点atr(状压DP)
- BZOJ 1097: [POI2007]旅游景点atr 状压,预处理,最短路
- BZOJ 1097: [POI2007]旅游景点atr spfa+状压dp
- 1097: [POI2007]旅游景点atr dijkstra+状压dp
- BZOJ1097: [POI2007]旅游景点atr
- BZOJ1097: [POI2007]旅游景点atr
- BZOJ1097: [POI2007]旅游景点atr
- BZOJ1097 [POI2007]旅游景点atr
- BZOJ 1097: [POI2007]旅游景点atr 最短路 堆优Dijkstra 状压
- [BZOJ1097][POI2007]旅游景点atr(状压dp)
- [BZOJ1097][POI2007]旅游景点atr(状压dp)
- bzoj1097[POI2007]旅游景点atr spfa+状压DP
- bzoj1097: [POI2007]旅游景点atr[最短路预处理+状压dp]
- MyEclipse 快捷键
- Shell学习if判断字符串
- java观察者模式及实现例子
- 幂和阶乘 UVa10780
- jsp格式化字符串
- BZOJ 1097 [POI2007]旅游景点atr
- iOS7修改UITabBar文本颜色以及解决自定义选中图片显示为默认蓝色的问题
- nginx网络服务器上如何阻止特定用户代理(UA)
- Spring 之注解事务 @Transactional
- php学习之 基础一
- HTML学习笔记
- SDUT 2278----商人的诀窍
- handler和实现接口的方式实现按钮的点击功能
- MPEG-2 TS码流分析