NC53269. 卡片占卜
描述
输入描述
第一行,五个正整数A,B,C,D,E,意义如题目描述;
第二行,一个正整数N,意义如题目描述;
接下来N行描述操作,一行两个正整数,意义如题目描述。
输出描述
输出一行,如果占卜能够结束,则输出一个正整数,表示占卜的最小耗时;如不能,输出-1。
示例1
输入:
1 2 3 4 5 3 2 3 2 6 4 10
输出:
12
说明:
最初的卡片序列为IOOIIIOOOOIIIII;示例2
输入:
1 1 1 1 1 1 1 1
输出:
-1
C++11(clang++ 3.9) 解法, 执行用时: 78ms, 内存消耗: 8952K, 提交时间: 2020-08-12 19:44:31
#include<bits/stdc++.h> #define LL long long #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; int R(){ int x;bool f=1;char ch;_(!)if(ch=='-')f=0;x=ch^48; _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;} const int N=5e5+5; int n,a[6],head[N],cnt;LL dis[N],ans=2e18; struct edge{int to,nex,w;}e[N<<1]; struct node{ int x;LL w; bool friend operator <(node a,node b){return a.w>b.w;} };priority_queue<node>q; void add(int s,int t,int w){e[++cnt]=(edge){t,head[s],w},head[s]=cnt;} void dij(int s){ for(int i=0;i<=a[5];i++)dis[i]=2e18; dis[s]=0; q.push((node){s,0}); while(!q.empty()){ node now=q.top();q.pop(); if(now.w!=dis[now.x])continue; for(int v,k=head[now.x];k;k=e[k].nex) if(dis[v=e[k].to]>dis[now.x]+e[k].w) dis[v]=dis[now.x]+e[k].w,q.push((node){v,dis[v]}); } return; } int main(){ for(int i=1;i<=5;i++)a[i]=a[i-1]+R(); n=R(); for(int i=1,u,v;i<=n;i++) u=R()-1,v=R(),add(u,v,v-u),add(v,u,v-u); dij(a[1]); LL s1=dis[a[2]],s2=dis[a[3]],s3=dis[a[4]]; dij(a[2]); ans=min(min(ans,s2+dis[a[4]]),s3+dis[a[3]]); dij(a[3]); ans=min(ans,s1+dis[a[4]]); printf("%lld\n",ans==2e18?-1:ans); return 0; }