sgu 103 Traffic Lights

这道题难得不是算法,而是处理。

题意就是让你求最短路,只有当两个点在某一秒颜色相同时,这条边才可以通行,输入首先给你 起点和终点, 然后给你 点数和边数,
接下来 n 行 初始颜色,初始颜色持续时间,蓝色持续时间,紫色持续时间。 再接下来m行,无向边的起点和终点以及通过所需的时间。

题意他说的有些模糊,样例我看了很多遍也不对,后来才发现如果你在某一秒到达一个点,这一秒颜色和下一个点相同,但是下一秒这个点就要变色,那么是不能在这一秒走的,这个具体处理起来很麻烦

这篇博客说的很详细,戳链接:http://www.cnblogs.com/Rinyo/archive/2012/11/29/2795030.html

上代码……


#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#define N 350
#define M 15000*2
#define inf 1<<30
using namespace std;

int n, m, S, T;
int p[N] = {0}, next[M], v[M], bnum = 0, c[M], fa[N];
int dis[N], vis[N], firstcolor[N], firstremain[N], remain[N][2];

void addbian(int x, int y, int z)
{
bnum++; next[bnum] = p[x]; p[x] = bnum;
v[bnum] = y; c[bnum] = z;
bnum++; next[bnum] = p[y]; p[y] = bnum;
v[bnum] = x; c[bnum] = z;
}

void calt(int now, int nowtime, int &color, int &changetime)
{
if (nowtime < firstremain[now])
{
color = firstcolor[now];
changetime = firstremain[now];
return;
}
int k;
k = (nowtime-firstremain[now]) % (remain[now][0]+remain[now][1]);
nowtime -= k;
if (firstcolor[now])
{
if (k < remain[now][0]) { color = 0; changetime = nowtime + remain[now][0]; }
else { color = 1; changetime = nowtime + remain[now][1] + remain[now][0]; }
}
else
{
if (k < remain[now][1]) { color = 1; changetime = nowtime + remain[now][1]; }
else { color = 0; changetime = nowtime + remain[now][0] + remain[now][1]; }
}
}

int gettime(int x, int y, int nowtime, int dis, int f)
{
int ca, cb, ta, tb, ta1, ca1;
calt(x, nowtime, ca, ta);
calt(y, nowtime, cb, tb);
if (ca == cb) return nowtime + dis;
if (ta == tb)
{
if (f == 0) return gettime(x, y, ta, dis, f+1);
else if (nowtime <= firstremain[x] || nowtime <= firstremain[y])
gettime(x, y, ta, dis, f+1);
else return inf;
}
return min(ta, tb) + dis;
}

void spfa()
{
queue<int> q;
for (int i = 1; i <= n; ++i) { vis[i] = 0; dis[i] = inf; }
q.push(S); dis[S] = 0; vis[S] = 1;
while (!q.empty())
{
int now = q.front(); q.pop();
int k = p[now];
while (k != 0)
{
int t = gettime(now, v[k], dis[now], c[k], 0);
if (dis[v[k]] > t)
{
dis[v[k]] = t; fa[v[k]] = now;
if (!vis[v[k]])
{
vis[v[k]] = 1;
q.push(v[k]);
}
}
k = next[k];
}
vis[now] = 0;
}
}

void print(int now)
{
if (now == S) printf("%d ", S);
else
{
print(fa[now]);
if (now != T) printf("%d ", now);
else printf("%d\n", T);
}
}

int main()
{
scanf("%d%d", &S, &T);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
{
char s[2];
scanf("%s", s);
if (s[0] == ‘B‘) firstcolor[i] = 0;
else firstcolor[i] = 1;
scanf("%d%d%d", &firstremain[i], &remain[i][0], &remain[i][1]);
}
for (int i = 1; i <= m; ++i)
{
int x, y, z; scanf("%d%d%d", &x, &y, &z);
addbian(x, y, z);
}
spfa();
if (dis[T] == inf)
{
printf("0\n");
return 0;
}
printf("%d\n", dis[T]);
print(T);
}

sgu 103 Traffic Lights,布布扣,bubuko.com

时间: 2024-10-19 16:22:36

sgu 103 Traffic Lights的相关文章

SGU 103. Traffic Lights 带限制最短路

每个点有2中颜色 只有一条路上的两个点颜色一样才能通过这条路 最短路加上等待的时间处理 处理的是参考别人的 唉还是太弱了 #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <algorithm> using namespace std; int s, e; int n, m; int a[333]; int b[333]; int c[

[2016-04-17][Gym][100947][A][Traffic Lights]

时间:2016-04-17 16:16:03 星期日 题目编号:[2016-04-17][Gym][100947][A][Traffic Lights] 题目大意:给出红黄绿灯的时间,刚刚转到绿灯,给出当时到达路口的时间,问到达路口的时候,灯的状态 分析:直接计算即可 #include<cstdio> using namespace std; int main(){ int x,g,y,r,t; scanf("%d",&t); while(t--){ scanf(&

Traffic Lights - SGU 103(最短路)

题目大意:有一个城市的路线图,有N个交叉点,每两个交叉点之间只有一条路,现在想从交点u去交点v,不过这个路的交通比较特别,每个路都有一个交通灯,灯有两种颜色,蓝色和紫色,例如一条路线在交点s,t之间,如果想从s走到t,那么只有等s和t的交通灯的颜色一致的时候才可以从s走,求出来从u到v的最短时间. 分析:比较明显能看出来是一个最短路问题,不过里面夹杂的这个交通灯比较恶心,要随时能求出来两点点下一个相同颜色的时间,如果使用时间去枚举无疑是个比较笨的方法,注意到有个剩余时间,并且交通灯的每种颜色存在

TRAFFIC LIGHTS POJ 1158

题目大意: 在Dingilville 城市安排是一种不同寻常的方式,每个交叉路口有一条道路连接,一条道路最多连接两个不同的交叉路口.每个交叉路口不能连接他自己.道路旅行一端到另一端的时间是相同的,任何一个交叉路口都有一个红绿灯,它在任意时刻只能有红色或者绿色.当且仅当两个交叉路口的灯的颜色一样的时候才允许从一个交叉路口到达另一个交叉路口.如果一辆车到达一个交叉路口的时候这个灯刚好转换,那么它必须考虑这个灯的颜色.允许车辆在交叉路口等待. 给你这个城市的地图如下: 所有道路的通过时间是整数,每个交

sgu100~199题解

老东西了..发上来吧.. Sgu题解系列  南开中学邹事成 100:A+B略 101:Domino 给n块多米诺骨牌,每张骨牌两端各有从1到6的一个数字,现在要把这些骨牌排成一列,使相邻的两块骨牌相对的面所写的数字一样. 可以把每一块多米诺骨牌想象成一条边,把面上写的数字抽象成点,比如一块骨牌正面写的1反面写的2就想象成连了一条从1到2的边,那么这就是求一条有重边的欧拉回路了,dfs一下即可. 102:Coprimes给定n求从1到n中与n互质的数的个数. 可以把n质因数分解后直接代入欧拉函数.

words

英语指路常用单词 the one-way street单行道traffic light红绿灯 fork road三叉路口intersection/crossroad?十字路口T road?丁字路口intersection/crossroads/junction/clover-leaf?立交桥 underground channel/Underpass地下通道gas station?加油站be far from?距离某处很远be nearby?距离某处很近go straight across/to

《论工业社会及其未来》—泰德.卡辛斯基

中文译文基于1996年中国文史出版社<轰炸文明——发往人类未来的死亡通知单>,原译者王小东 INTRODUCTION 介绍 1. The Industrial Revolution and itsconsequences have been a disaster for the human race. They have greatlyincreased the life-expectancy of those of us who live in "advanced"cou

XIII Open Cup named after E.V. Pankratiev. GP of SPb

A. Graph Coloring 答案为$1$很好判,为$2$只需要二分图染色,对于$3$,首先爆搜哪些边要染成第$3$种颜色,然后二分图染色判定即可. B. Decimal Fraction 枚举前缀,那么只需要求出后面部分的最小循环节即可,将串翻转之后进行KMP,循环节长度$=i-next[i]$. 时间复杂度$O(n)$. C. Teams of Equal Power 首先将球员按能力值从大到小排序,假设一队的队长能力值比二队队长高,那么显然一队队长只能是第一个人,枚举二队队长,然后看

杭电ACM分类

杭电ACM分类: 1001 整数求和 水题1002 C语言实验题——两个数比较 水题1003 1.2.3.4.5... 简单题1004 渊子赛马 排序+贪心的方法归并1005 Hero In Maze 广度搜索1006 Redraiment猜想 数论:容斥定理1007 童年生活二三事 递推题1008 University 简单hash1009 目标柏林 简单模拟题1010 Rails 模拟题(堆栈)1011 Box of Bricks 简单题1012 IMMEDIATE DECODABILITY