pta 超能力者大赛(测试点8,测试点9)

一道模拟题,想要ac的话还是挺麻烦的。简单说一下我的思路,不断用找下一个对手所在的城市,如果不能到达该城市或找不到符合条件的对手,判断输赢,否则,前往该城市。到达该城市后,判断能不能在时间结束前干掉对手,如果不行,输出Game over,否则,干掉对手,更新联盟,然后判断能不能待到第二天,如果可以(当且仅当当前城市还有人),干掉剩余人,在重新找对手,否则,直接重新找对手,且下次对手不能为当前城市。

我的代码从day0开始的,所以如果开局就胜利或输,应该令day++;同时这也是测试点8考察的点。

测试点9:如果你在一个城市中,且不能待到第二天,你要保证你下一个找的对手不在你当前这个城市中。

ac代码:

#include<bits/stdc++.h>
#define ll long long
#define ios ios::sync_with_stdio(0)
#define pii pair<int,int>
#define x first
#define y second
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dwn(i,a,b) for(int i=a;i>=b;i--)
#define repp(i,a,b) for(int i=a;i<b;i++)
#define dwnn(i,a,b) for(int i=a;i>b;i--)
#define lowbit(x) x&-x
#define mm memset
#define endl '\n'
#define INF 0x3f3f3f3f
#define debug(x) cout<<"x = "<<x<<endl
#define PB push_back
using namespace std;
const int N = 1e6 + 5,M = 205;
int n,m,e,d,mp[M][M],path[M][M],day,lastcity = -1;
bool lose[N];
vector<pii> city[M];
pii p[N];
void input() {
	lose[0] = true;
	mm(mp,INF,sizeof(mp));
	mm(path,INF,sizeof(path));
	cin>>n>>m>>e>>d;
	repp(i,0,n) {
		cin>>p[i].x>>p[i].y;
		city[p[i].x].PB({i,p[i].y});
	}
	rep(i,1,e) {
		int u,v,w;
		cin>>u>>v>>w;
		mp[u][v] = mp[v][u] = w;
		mp[u][u] = mp[v][v] = 0;
		path[u][u] = path[v][v] = 0;
		path[u][v] = path[v][u] = 1;
	}
	repp(k,0,m) {
	repp(i,0,m) {
	repp(j,0,m) {
		if(mp[i][j] > mp[i][k] + mp[k][j]) {
			mp[i][j] = mp[i][k] + mp[k][j];
			path[i][j] = path[i][k] + path[k][j];
		}
		else if(mp[i][j] == mp[i][k] + mp[k][j] 
		&& path[i][j] > path[i][k] + path[k][j]) {
			path[i][j] = path[i][k] + path[k][j];
		}
	}
	}
	}
}
bool iswin() {
	repp(i,1,n) {
		if(!lose[i]) return false;
	}
	return true;
}
int find() {
	bool isb = false;
	int myable = p[0].y,mycity = p[0].x,ne = 0;
	int mia = INF,mib = INF,mic = INF,mid = INF;
	repp(i,1,n) {
		if(lose[i]) continue;
		if(p[i].y > myable) {
			isb = true;
			continue;
		}
		if(p[i].x == lastcity) {
			continue;
		}
		int dif = abs(p[i].y - myable);
		int dis = mp[mycity][p[i].x];
		int num = path[mycity][p[i].x];
		int id = p[i].x;
		if(dif < mia) {
			mia = dif;
			mib = dis;
			mic = num;
			mid = id;
			ne = i;
		}
		else if(dif == mia) {
			if(dis < mib) {
				mia = dif;
				mib = dis;
				mic = num;
				mid = id;
				ne = i;
			}
			else if(dis == mib) {
				if(num < mic) {
					mia = dif;
					mib = dis;
					mic = num;
					mid = id;
					ne = i;
				}
				else if(num == mic) {
					if(id < mid) {
						mia = dif;
						mib = dis;
						mic = num;
						mid = id;
						ne = i;
					}
				}
			}
		}
	}
	if(ne == 0) {
		if(isb) {
			day ++;
			printf("Lose on day %d with %d.",day,p[0].y);
		}
		else {
			if(day == 0)
				printf("WIN on day %d with %d!",day+1,p[0].y);
			else 
				printf("WIN on day %d with %d!",day,p[0].y);
		}
		return -1;
	}
	if(day + mp[p[0].x][p[ne].x] > d) {
		printf("Game over with %d.",p[0].y);
		return -1;
	}
	if(p[0].x != p[ne].x) {
		printf("Move from %d to %d.\n",p[0].x,p[ne].x);
		lastcity = p[ne].x;
		day += mp[p[0].x][p[ne].x];
		if(day > d) return -1;
	}
	return ne;
}
void update(int ne) {
	day ++;
	if(day > d) {
		printf("Game over with %d.",p[0].y);
		return ;
	}
	printf("Get %d at %d on day %d.\n",p[ne].y,p[ne].x,day);
	lose[ne] = true;
	p[0].x = p[ne].x;
	p[0].y += p[ne].y;
	int sum = 0;
	bool f = true;
	repp(i,0,city[p[ne].x].size()) {
		int able = city[p[ne].x][i].y;
		int id = city[p[ne].x][i].x;
		if(lose[id]) continue;
		if(able > p[0].y) {
			f = false;
			continue;
		}
		else {
			sum += able;
			lose[id] = true;
		}
	}
	if(sum > p[0].y) f = false;
	if(f && sum != 0) { // 可以待到第二天 
		day ++;
		if(day > d) {
			printf("Game over with %d.",p[0].y);
			return ;
		}
		printf("Get %d at %d on day %d.\n",sum,p[ne].x,day);
		p[0].y += sum;
	} 
	if(!f) { // 不能待到第二天 
		if(sum != 0) {
			p[n].x = p[ne].x,p[n].y = sum;
			city[p[ne].x].PB({n,sum});
			n ++;
		}
	}
}
void solve() {
	input();
	while(day <= d) {
		int ne = find();
		if(ne == -1) break; 
		update(ne);
	}
}
int main() {
	ios;
	solve();
	return 0;
}

  • 16
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值