【NOIP2012普及组】文化之旅
来源:互联网 发布:军爷捏脸数据 编辑:程序博客网 时间:2024/06/06 06:31
这题看起来是一道最短路的题,实际上单纯的最短路不法判断下一个到达的点有没有和以前走过的任何一点冲突。
但是因为数据太弱,裸地最短路算法好像也能过。
实际上这题的正解应该是:最短路预处理+深搜/宽搜
看完数据范围后发现两点间距离值为整数,所以可以用Dijkstra+堆优化从终点跑最短路。
再从起点跑个搜索就可以了,check函数用来判断是否有文化冲突
在dfs时可以用最优性剪枝,如果当前距离D+之前走过的距离+到重点的距离大于以求出的最优值,这种情况应被剪枝
存图的方式是用数组模拟邻接表。
AC代码:
#include <iostream>#include <cstdio>#include <queue>#include <cstring>#define min(a,b) (a<b ?a:b)const int INF=0x3f3f3f3f;using namespace std;int n,cul[101],head[101],tot=0,dist[101]; struct node{ //用于优先级队列 int pos,w; node(int a,int b){pos=a;w=b;} bool operator < (const node &a)const{ //重载运算符 return w>a.w; }};struct graph{ //存图 int v,w,next;}edge[10001];void add_edge(int u,int v,int w){ //建图 edge[++tot]=(graph){v,w,head[u]}; head[u]=tot;}priority_queue<node>Q;bool visited[101]; void dij(int m){ //最短路:Dijkstra+堆优化 memset(dist,0x3f,sizeof(dist)); dist[m]=0;Q.push(node(m,0)); while (!Q.empty()){ node temp=Q.top();Q.pop(); if (visited[temp.pos]) continue; int w=temp.w,u=temp.pos,cur=head[u]; for (int i=cur;i;i=edge[i].next){ if (w+edge[i].w<dist[edge[i].v]){ dist[edge[i].v]=w+edge[i].w; Q.push(node(edge[i].v,dist[edge[i].v])); } } visited[u]=true; }}bool clash[101][101]; //读入文化是否冲突int been[10001]; //开大一点,记录以来过的文化int t,k,ans=INF;bool check(int x){ //判断第x种文化是否与之前来过文化冲突 for (int i=1;i<=tot;i++) if (clash[been[i]][cul[x]]) return false; return true;}void dfs(int x,int val){ //深搜 bool f=false; if (x==t) ans=min(ans,val); if (val>=ans) return; visited[cul[x]]=true; int temp=tot; for (int i=head[x];i;i=edge[i].next){ int v=edge[i].v; if (!visited[cul[v]] && !clash[cul[v]][cul[x]] && check(v) && val+edge[i].w+dist[v]<ans) //最优性剪枝 been[++tot]=cul[v],f=true,dfs(v,val+edge[i].w); } tot=temp; //还原现场 if (!f) visited[cul[x]]=false;}int main(){ ios::sync_with_stdio(false); int m,s,u,v,d; cin>>n>>k>>m>>s>>t; for (int i=1;i<=n;i++) cin>>cul[i]; for (int i=1;i<=k;i++) for (int j=1;j<=k;j++) cin>>clash[i][j]; for (int i=1;i<=m;i++){ cin>>u>>v>>d; add_edge(u,v,d);add_edge(v,u,d); } dij(n); //从终点开始跑最短路 memset(visited,false,sizeof(visited)); dfs(s,0); //从起点开始dfs if (ans!=INF) cout<<ans<<endl; else cout<<-1<<endl; return 0;}
阅读全文
0 0
- NOIP2012 普及组 T4 文化之旅
- 【NOIP2012普及组】文化之旅
- NOIP2012 JuniorT4 文化之旅
- NIOP2012普及组-文化之旅
- Noip2012普及组
- NOIP2012普及组-寻宝
- NOIP2012普及组-寻宝
- NOIP 2012 普及组 复赛 culture 文化之旅
- 2012 NOIP普及组T4 文化之旅
- [普及] NOIP 2012 文化之旅
- luogu1078【2012普及】文化之旅(dfs)
- noip2012 文化之旅 (深搜,最优性剪枝)
- 【模拟】【noip2012普及组】寻宝
- NOIP2012普及组解题报告
- 【NOIP2012普及组】摆花
- [NOIP2012普及组]摆花
- NOIP2012普及组-质因数分解
- [Noip2012普及组]摆花
- 避免滑动tableView时NSTimer 暂停
- 火车票系统模拟
- python清屏
- 人工智能从入门到精通(5)
- 一 蓝牙概述
- 【NOIP2012普及组】文化之旅
- 使用python来抠图
- android AlertDialog 对话框的基本使用
- View 的工作流程---结合HenCoder教程和《Android开发艺术探索》的总结
- BZOJ2733 永无乡 【splay启发式合并】
- c语言操作符
- android 模拟 再按一次退出程序onKeyDown
- Js复习
- 飞龙的程序员书单 – 思想、工程、架构、职业发展