先传个笔试成绩的截图:
这次算是成绩最好的一次了,笔试结束后仍然可以练习,地址戳https://code.google.com/codejam/contest/10214486/dashboard。
A. Travel
一看就是图论当中最短路的变形,但是边的权重会随着时间发生变化。对于dijkstra或者Bellman Ford之类的最短路算法,它们本质上都是动态规划,需要满足最优子结构性质,如果边权重随着时间的变化是不规则的,那么这些算法都无法保证得到最优解。
但是题目中有一个条件: cost(i)≤cost(i+1)+1 ,换句话说,不可能出现从一个顶点晚出发却早到终点的情况,于是不管是dijkstra, bellman ford, spfa都是仍然适用的,预先计算出1在所有时间点到所有点的最短路, O(1) 即可回答每一个查询。
#include <bits/stdc++.h>
#define FOR(i, n) for (int i = 0; i < (int)n; ++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> point;
const int INF = INT_MAX / 2;
vector<int> cost[505][505];
void solve() {
int N, M, K, x, y, c;
scanf("%d %d %d", &N, &M, &K);
FOR(i, N + 1) FOR(j, N + 1) cost[i][j].clear();
FOR(i, M) {
scanf("%d %d", &x, &y);
FOR(j, 24) {
scanf("%d", &c);
cost[x][y].push_back(c);
cost[y][x].push_back(c);
}
}
int dis[505][24];
FOR(i, N + 1) FOR(j, 24) dis[i][j] = INF;
FOR(start, 24) {
// spfa
vector<bool> inq(N + 1, false);
dis[1][start] = 0; inq[1] = true;
queue<int> q;
q.push(1);
while (!q.empty()) {
int tp = q.front(); q.pop(); inq[tp] = false;
for (int i = 1; i <= N; ++i) {
if (cost[tp][i].empty()) continue;
int md = (start + dis[tp][start]) % 24;
if (dis[i][start] > dis[tp][start] + cost[tp][i][md]) {
dis[i][start] = dis[tp][start] + cost[tp][i][md];
if (!inq[i]) { q.push(i); inq[i] = true; }
}
}
}
}
int D, S;
FOR(i, K) {
scanf("%d %d", &D, &S);
if (dis[D][S] == INF) {
cout << " -1";
}
else cout << " " << dis[D][S];
}
cout << endl;
return;
}
int main() {
int TestCase;
cin >> TestCase;
FOR(caseID, TestCase) {
cout << "Case #" << caseID + 1 << ":";
solve();
}
return 0;
}
B.gWheels
我读了半天题才看明白什么意思。。。说白了就是有三个数组 a[1],a[2]...a[Np] , b[1],b[2]...b[N