R7-3 超能力者大赛(PTA)

提前声明:本代码仅能够过样例,由于提交端口关闭,是否完全正确目前不清楚

#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;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值