zcmu 1603 卡斯丁狗的战舰帝国(并查集+模拟)

思路:看到题目我只知道,普通的暴力模拟是不行的,但是不知道用什么办法优化,然后看到网上的大佬们用了并查集恍然大悟;

用并查集维护每条船攻击后的根节点,最后输出查询位置的根节点就行,如果在期间存在该位置的根节点的下个位置的根节点也已经沉了,说明所有的船都已经沉了,退出循环;

代码如下:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include<string>
#include <cmath>
#include<stack>
using namespace std;
int a[100050], b[100050];
int f[100050];
int find(int x)
{
	if (x == f[x])//说明已经是根节点了
		return x;
	else
		return f[x] = find(f[x]);//如果不是根节点,则找它的父节点
}

int main()
{
	int n, m;

	while (~scanf("%d%d",&n,&m))
	{
		for (int i = 1; i <=n; i++)
			scanf("%d", &a[i]);
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &b[i]);
			f[i] = i;
		}
		int flag = 0;
		f[n+1] = 1;//*****************这步很重要!!!!******************把最后一条船后面的位置设置成1,说明这个位置指向对方的第一条船
		//用来满足条件中的:如果不存在,则攻击最远离 i 并且< i 没有死亡的敌方战舰。
		
		while(m--)
		{
			if (flag)
				break;
			for (int i = 1; i <= n; i++)
			{
				int t = find(i);
				a[t] -= b[i];

				if (a[t] <= 0)//如果i位上的根节点已经沉没了
				{
					int tt = find(t + 1);//找根节点的下个节点的根节点
					if (a[tt] <= 0)//说明该点的根节点已经沉了,说明战斗已经胜利
					{
						flag = 1;
						break;
					}
					else
					{
						f[t] = tt;//如果没有沉,说明战斗还没有结束,f[t]指向根节点
					}
				}
			}
		}
		int c;
		int i;
		scanf("%d", &c);
		while (c--)
		{

			scanf("%d", &i);
			
			if (flag)
				printf("win\n");
			else
				printf("%d\n", find(i));
		}
	}


	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值