提前声明:本代码仅能够过样例,由于提交端口关闭,是否完全正确目前不清楚
#include <iostream>
#include <vector>
#include <cmath>
#include <cstdio>
#define inf 200005
using namespace std;
typedef struct node {
int value;
int city;
int fa;
int num;
bool exist;
} superman;
superman man[200005];
vector <int> city[205];
int A[205][205], path[205][205], vis[205];
int n, citynum, m, d, cnt;
void floyd() {
for (int k = 0; k < citynum; k++)
for (int i = 0; i < citynum; i++)
for (int j = 0; j < citynum; j++) {
if (A[i][j] > A[i][k] + A[k][j]) {
A[i][j] = A[i][k] + A[k][j];
path[i][j] = path[i][k] + path[k][j];
}
}
}
int main() {
scanf("%d%d%d%d", &n, &citynum, &m, &d);
cnt = n;
for (int i = 0; i < citynum; i++)
for (int j = 0; j < citynum; j++) {
if (i == j) {
A[i][j] = 0;
path[i][j] = 0;
}
else {
A[i][j] = inf;
path[i][j] = inf;
}
}
for (int i = 0; i < n; i++) {
scanf("%d%d", &man[i].city, &man[i].value);
int tmp_city = man[i].city;
city[tmp_city].push_back(i);
man[i].fa = i;
man[i].exist = 1;
man[i].num = 1;
}
for (int i = 0; i < m; i++) {
int city1, city2, w;
scanf("%d%d%d", &city1, &city2, &w);
A[city1][city2] = w;
A[city2][city1] = w;
path[city1][city2] = 1;
path[city2][city1] = 1;
}
floyd();
superman me = man[0];
int nowday = 1;
int kill_count = 0;
while (1) {
// 循环结束的条件
// 1.比赛时间结束,且没打完所有超能力者
// if (nowday >= d) {
// printf("Game over with %d.\n", me.value);
// break;
// }
int Min = inf, Mini = -1;
// 找超能力者,比你小,能力与你最接近,距离你最近,途径城市最少,编号最小
for (int i = 1; i < n; i++) {
int reali = man[i].fa;
if (man[reali].value - me.value > 0 || vis[man[reali].city] || !man[i].exist) continue;
int ABS = abs(man[reali].value - me.value);
if (ABS < Min) {
Min = ABS;
Mini = reali;
}
else if (ABS == Min) {
if (A[man[reali].city][me.city] < A[man[Mini].city][me.city])
Mini = reali;
else if (A[man[reali].city][me.city] == A[man[Mini].city][me.city] &&
path[man[reali].city][me.city] < path[man[Mini].city][me.city])
Mini = reali;
else if (A[man[reali].city][me.city] == A[man[Mini].city][me.city] &&
path[man[reali].city][me.city] == path[man[Mini].city][me.city] &&
man[reali].city < man[Mini].city) Mini = reali;
}
}
if (nowday > d) {
if (Mini == -1) printf("Lose on day %d with %d.\n", nowday - 1, me.value);
else printf("Game over with %d.\n", me.value);
break;
}
// 找不到这样的超能力者
// 3.在比赛时间内(包括最后一天)无路可走
if (Mini == -1) {
printf("Lose on day %d with %d.\n", nowday, me.value);
break;
}
// 找到了这样的超能力者
else {
if (me.city != man[Mini].city)
printf("Move from %d to %d.\n", me.city, man[Mini].city);
nowday += A[man[Mini].city][me.city] - 1;
// 行程超时了
if (nowday >= d && me.city != man[Mini].city) {
printf("Game over with %d.\n", me.value);
break;
}
// 没有超时
// 如果在本地,现在就可以干,否则第二天开干
//if (me.city != man[Mini].city) nowday++;
// 只有第一次会有可能在本地
nowday++;
me.city = man[Mini].city;
me.value += man[Mini].value;
man[Mini].exist = 0;
// 又干了一个,kill_count++
kill_count += man[Mini].num;
printf("Get %d at %d on day %d.\n", man[Mini].value, me.city, nowday);
nowday++;
// 1.比赛时间结束,且没打完所有超能力者
if (nowday > d && kill_count < n - 1) {
printf("Game over with %d.\n", me.value);
break;
}
// 1.比赛时间结束,且打完所有超能力者
else if (nowday > d && kill_count == n - 1) {
printf("WIN on day %d with %d!\n", nowday - 1, me.value);
break;
}
// 干完架的第二天
// 能力比你弱的组队
for (int i = 0; i < city[me.city].size(); i++) {
int tmp = city[me.city][i];
// 每次打完都会更新exist
man[tmp].exist = man[man[tmp].fa].exist;
// 打过了跳过
if (!man[tmp].exist || !tmp) continue;
int realv = man[man[tmp].fa].value;
if (realv <= me.value) {
man[tmp].fa = cnt;
man[cnt].value += man[tmp].value;
man[cnt].city = me.city;
man[cnt].exist = 1;
man[cnt].fa = cnt;
man[cnt].num++;
}
}
cnt++;
// 看看这个城市还有没有能打的
int flag1 = 0, sum = 0, cainiao = 0;
for (int i = 0; i < city[me.city].size(); i++) {
int tmp = city[me.city][i];
// 打过了跳过
if (!man[tmp].exist || !tmp) continue;
int realv = man[man[tmp].fa].value;
if (realv > me.value) {
flag1 = 1;
break;
}
sum += man[tmp].value;
// 记录有多少只菜鸟
cainiao++;
}
// 全是菜鸟,一起上,一天干一个,其实只要花一天就够了
// 实际上只有一个联盟,想想为什么
if (!flag1 && sum) {
me.value += sum;
// 这个城市已经没有超能力者了
vis[me.city] = 1;
kill_count += cainiao;
printf("Get %d at %d on day %d.\n", sum, me.city, nowday);
// 2.在比赛时间内击败了超能力者
if (kill_count == n - 1) {
printf("WIN on day %d with %d!\n", nowday, me.value);
break;
}
nowday++;
}
// 打不过有风险,跑
// 回到循环开始
}
}
return 0;
}