Educational Codeforces Round 41 (Rated for Div. 2)

题目链接:点击打开链接

A. Tetris

(水题)

题意:给出n列的俄罗斯方块游戏,m步操作,随后m个数表示当前一个1*1的俄罗斯方块投放在第几列,当最下面一行都有方块时会消去并且计分,问当m次操作后积分为多少?

解法:题目要求最终消去了多少行,即求m步操作在不同列投放方块的最小值即可。

代码如下

#include <iostream>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
int a[1500];
int main()
{
	int n, m, x;
	cin >> n >> m;
	for (int i = 0; i < m; i++)
	{
		cin >> x;
		a[x]++;
	}
	int ans = inf;
	for (int i = 1; i <= n; i++)
		ans = min(ans, a[i]);
	cout << ans << endl;
	return 0;
}

B. Lecture Sleep

(水题)

题意:某学生上课容易犯困,第一行给出n,m表示n个时间段,和提神药水持续时间m秒,第二行给出n个数a[i],表示第i个时间段该同学可以记录a[i]的知识点,第三行给出n个数b[i],表示第i个时间段该同学的状态,1表示醒着,0表示睡着了(使用提神药水可以醒来)。输出该同学最多能记录多少知识点(即最优的提神药水使用时段的贪心)。

解法:即求解提神药水在各个时间点使用能获得的最大知识点值(不包含原本醒着的),再加上原本醒着能获得的知识点值。

代码如下

#include <iostream>
using namespace std;
const int maxn = 1e5 + 500;
int a[maxn], b[maxn];
int main()
{
	int n, k;
	cin >> n >> k;
	for (int i = 0; i < n; i++)
		cin >> a[i];
	for (int i = 0; i < n; i++)
		cin >> b[i];
	int ans = 0, sum = 0, x = 0, y = 0;
	for (int i = 0; i < k; i++)
		if (b[i] == 0)sum += a[i];
	ans = sum; y = k - 1;
	for (int i = k; i < n; i++)
	{
		if (b[i] == 0)sum += a[i];
		if (b[i - k] == 0)sum -= a[i - k];
		if (sum > ans)
		{
			ans = sum;
			x = i - k;
			y = i;
		}
	}
	sum = ans;
	for (int i = 0; i < n; i++)
		if (b[i] == 1)sum += a[i];
	cout << sum << endl;
	return 0;
}

C. Chessboard

(水题)

题意:一个被2n*2n的黑白棋盘被分成了4部分,每部分都为n*n(n为奇数),由于某些原因导致棋盘中的格子颜色不对,现在要求你用最少的步数给它上色还原为2n*2n的黑白格棋盘。题目给出一个n,随后给出4个n*n的1,0表(黑白表),用这4个表随机拼凑(位置可以交换,不可旋转)然后改变格子颜色使它还原为2n*2n的黑白棋盘。输出最少染色次数。

解法:求每个n*n的转换为左上角是1和左上角是0的2种情况的分别最少染色次数,再进行随机搭配(2个左上角为1的和2个左上角为0的组合)得到min_ans。

代码如下

#include <stdio.h>
#include <string>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include<vector>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
#define  ll long long 
const int maxn = 1e5 + 500;
int a[10], b[10];
char s[5][105][105];
int main()
{
	int n;
	while (~scanf("%d", &n))
	{
		memset(a, 0, sizeof(a));
		memset(b, 0, sizeof(b));
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < n; j++)
				scanf("%s", &s[i][j]);
		//类型1 左上角为1
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < n; j++)
				for (int k = 0; k < n; k++)
				{
					if ((j + k) % 2 == 0 && s[i][j][k] == '0')a[i]++;
					else if ((j + k) % 2 == 1 && s[i][j][k] == '1')a[i]++;
				}
		//类型2 左上角为0
		for (int i = 0; i < 4; i++)
			for (int j = 0; j < n; j++)
				for (int k = 0; k < n; k++)
				{
					if ((j + k) % 2 == 0 && s[i][j][k] == '1')b[i]++;
					else if ((j + k) % 2 == 1 && s[i][j][k] == '0')b[i]++;
				}
		int ans = inf,s1=0;
		for (int i = 0; i < 4; i++)
			s1 += b[i];
		for(int i=0;i<4;i++)
			for (int j = i + 1; j < 4; j++)
			{
				int x = a[i] + a[j] + s1 - b[i] - b[j];
				ans = min(ans, x);
			}
		cout << ans << endl;
	}
	return 0;
}

D. Pair Of Lines 

(计算几何)

题意:给出n个点的坐标(x,y),问你是否能用2条直线过所有点,可以输出YES,反之NO。

解法:对于这种情况,那我们当n<=4是一定成立的,n>4的时候我们可以任意取3个点,先以3点中的2点画一条直线,把该直线不能过的点存入vector中,在对剩下的所有点进行判断,它们是否都在一条直线上,是的话输出YES,不是则取3点中其他2点重复进行上步骤,直到3种情况都没办法实现,那么可以输出NO了。(其实就是一个散点图中,若能用2条直线覆盖所有点,那么容易取三点中的2点必然与其中一条直线重合,复杂问题简单化)

代码如下

#include <stdio.h>
#include <string>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include<map>
#include<vector>
using namespace std;
#define inf 0x3f3f3f3f
#define  ll long long 
const int maxn = 1e5 + 500;
struct node
{
	ll x, y;
}a[maxn];
bool Xmult(node p1, node p2, node p0)
{
	return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y) == 0 ? true : false;
}
int n;
int vis[maxn];
bool fun()
{
	vector<int>q;
	int key = 1;
	for (int i = 2; i < n; i++)
		if (!Xmult(a[0], a[1], a[i]))q.push_back(i);
	if (q.size() <= 2)return true;
	for (int i = 2; i < q.size(); i++)
		if (!Xmult(a[q[0]], a[q[1]], a[q[i]])) {
			key = 0; break;
		}
	if (key)return true;
	q.clear(); key = 1;
	for (int i = 1; i < n; i++)
		if (!Xmult(a[0], a[2], a[i]))q.push_back(i);
	if (q.size() <= 2)return true;
	for (int i = 2; i < q.size(); i++)
		if (!Xmult(a[q[0]], a[q[1]], a[q[i]])) {
			key = 0; break;
		}
	if (key)return true;
	q.clear(); key = 1;
	for (int i = 0; i < n; i++)
		if (!Xmult(a[1], a[2], a[i]))q.push_back(i);
	if (q.size() <= 2)return true;
	for (int i = 2; i < q.size(); i++)
		if (!Xmult(a[q[0]], a[q[1]], a[q[i]])) {
			key = 0; break;
		}
	if (key)return true;
	return false;
}
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
		scanf("%lld%lld", &a[i].x, &a[i].y);
	if (n<=4||fun())
		cout << "YES" << endl;
	else
		cout << "NO" << endl;
	return 0;
}

剩下的题留给dalao补充=。=

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值