肝题日志【二】

本文探讨了一道关于植物大战僵尸游戏的算法问题,如何利用有限的辣椒炸弹消灭最多僵尸。通过分析,指出原二维问题可简化为一维,并提出使用打擂台方法解决,但因效率问题需要采用快速读取策略。最终实现并得到AC码,同时指出该问题有其他解法,欢迎探讨。

在题库里偶然发现了一道挺有趣的题——辣椒炸弹

洛谷U265157 辣椒炸弹

题目描述

       植物大战僵尸这款游戏中,有一种植物武器叫辣椒炸弹,在草坪中的任意一格摆放它可以把草坪中该行上的所有僵尸瞬间消灭,也就是说,如果在第i行中任意位置摆放一个炸弹,第i行中的所有僵尸就瞬间都被杀死了。

       现在我们假定草坪有r行c列,草坪中有n只僵尸,僵尸不移动,现在给你k个辣椒炸弹,要求只能使用这K个炸弹来消灭这些僵尸,请问最多可以杀死多少只僵尸。

输入

第一行4个正整数r ,c ,k ,n。
接下来n行,每行两个正整数x,y,表示第x行的第y列中有一只僵尸。

输出

第一行输出最多可以杀死的僵尸数。
第二行按顺序输出所有被消灭的行,如果有不同方案,输出字典序最小的那种方案。

样例输入

4 5 2 6
1 3
2 3
3 1
4 4
4 5
4 5

样例输出

4
1 4

样例说明

方案 1和4,2和4,3和4 都是一样多的僵尸,但方案 1和4 的字典序最小。

题目范围

对于30%数据:0 < r , c<=50, n<=2500,
对于100%数据:0 < r , c<=1000, n<=1000000, k<= r

题目分析

第一个想到的就是用一个数组存储每一个僵尸的位置,但“0 < r , c<=1000”直接开一个1000000大小的数组太大了。注意辣椒炸弹一次性可以消灭一整行,所以僵尸在第几行我们是不用管的,数组也就从二维变成了一维。

这道题用打擂台的方法就可以解决了,即循环k次,每一次找到最多僵尸的那一行。然后再开一个数组用来存储在那些地方放了炸弹💣

#include <bits/stdc++.h>
using namespace std;
long long f[2000]={0}, a[2000]={0};
int r, c, k, n, x, y, i, j, s, ans=0;
int main()
{
	cin >> r >> c >> k >> n;
	for (i=1; i<=n; ++i)
	{
		cin >> x >> y;
		++f[x];
	}
	for (i=1; i<=k; ++i)
	{
		c = 0;
		for (j=1; j<=r; ++j)
		{
			if (f[j]>c)
			{
				c = f[j];
				s = j;
			}
		}
		ans += f[s];
		f[s] = 0;
		a[s] = 1;
	}
	cout << ans << endl;
	for (i=1; i<=r; ++i)
		if (a[i]) cout << i <<' ';
	return 0;
}

但这样子是过不了这一题的,会超时,需要用到快读

int read()
{
	char c;
	int f=1;
	while((c=getchar())<'0'||c>'9')
	 if(c=='-') f=-1;
	int res=c-'0';
	while((c=getchar())>='0'&&c<='9')
	 res=res*10+(c-'0');//终极写法(位运算):res=(res<<3)+(res<<1)+(c^48);
	return res*f;
}

这段代码在其他地方也有讲到,再此不详细叙述。

经过简化,就得到了最终的代码

AC码

#include <bits/stdc++.h>
using namespace std;
long long f[2000]={0}, a[2000]={0};
int r, k, n, i, j, s, ans=0, res;
char c;
void read()
{
	while((c=getchar())<'0' || c>'9');
	res = c-'0';
	while((c=getchar())>='0' && c<='9')
		res = res*10+(c-'0');
}

int main()
{
	cin >> r >> j >> k >> n;
	for (i=1; i<=n; ++i)
	{
		read();
		++f[res];
		read();
	}
	for (i=1; i<=k; ++i)
	{
		res = 0;
		for (j=1; j<=r; ++j)
		{
			if (f[j]>res)
			{
				res = f[j];
				s = j;
			}
		}
		ans += f[s];
		f[s] = 0;
		a[s] = 1;
	}
	cout << ans << endl;
	for (i=1; i<=r; ++i)
		if (a[i]) cout << i <<' ';
	return 0;
}

其实这道题也有其他解法,还请各位大佬们指点。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值