泉城高校友谊赛赛后总结

比赛中ABEKM这些题并不算太难, 我们队也很快做完了, 但是最后H题上耗费了大量的时间, 等最终确定思路开写又因为一些边界问题最终没能提交通过, 赛后将数组中存的差值改为绝对值后通过了题目, 也因为H题的缘故我们没有认真的去做L题, 赛后才知道L题也并不算太难,总之我们还是太菜了😭

A题

题目链接
大概的题意就是给你标有从1-N的数字的卡片, 给出每张卡片的数量, 让你找到两数字差值小于等于1 的卡片对, 让你求最大的对数。
这道题直接从1-N开始遍历,先统计当前数字卡片能组成的对数, 如果是奇数那下一个数字的卡片数量加上这个1,在继续遍历重复上述过程就可以得到最大对数了。

B题

题目链接
这个题是说, 刚开始你有1克黄金和1克白银, 在之后的n天了可以选择交易或者不交易, 交易规则是: 如果有黄金, 就将黄金交易为xa[i]克白银, a[i](a[i]是第i天给你的数字), 否则的话, 如果只有白银, 就将白银交易为x/a[i]克黄金。让你求n天后能获得的最大黄金量。(为了方便辨认以下x代表黄金量, y代表白银量)
很容易看出想要最后留有黄金, 那交易次数一定是偶数次, 且将白银转化为黄金时, y越大a[i]越小得到的黄金越多, 而要y大即将黄金变为白银时a[i]大,y = x
a[i]才会更大。经过简单验证会发现, 在一个连续的递减序列里, 用x乘以最大值, 可以得到这段序列里y的最大值, 用这个y除以这个序列的最小值就可以的到这个递减序列的最大x。所以就可以把a[1]-a[n]分为k个递减子序列, 在子序列的最大值处和最小值处进行交易即可, 当然要保证这个递减子序列元素个数至少为2, 毕竟要保证交易偶数次最后才能留有黄金。

E题

题目链接
在这里插入图片描述
这个题纯纯签到题了, 就是当a, b, c三个值中有一个是偶数的时候, 蓝色矩形和红色矩形的最小差值为0, 当都是奇数时, 蓝色矩形和红色矩形的最小差值就是a, b, c中最小的两的数的积

H题

题目链接
题意:
给你h*w的网格, 每个网格里有两个数字, 你可以让任意一个数字代表红色, 另一个代表蓝色, 然后让你从(1,1)位置到(h, w)位置, 且你只能向右和向下走, 让你求你所经过的所有格子的蓝色数字和红色数字的差的绝对值最小。
例:
在这里插入图片描述

这道题是我们赛后补的, 没能在比赛上做出来算是有点遗憾吧。
题目中每个格子中的两个数字那个是蓝色那个是红色都是让你自己来定义的, 这时候如果你是想统计从(1,1)到(h, w)所有的蓝色的和与红色的和然后在求绝对值是很麻烦的, 因为你不能预先知道那个是红色那个是蓝色。
既然是不确定的且最终结果也是取绝对值, 那我们不必知道那些数字是蓝色那些是红色, 我们只需要求这条路径上加上或者减去a[i] - b[i]这个值后得到的最终结果的绝对值的最小值。那么我们可以预处理处每个格子两个数的a[i]-b[i]的差值, 因为用两数差值来做后面会产生偏移量, 所以我们可以直接预处理处两数差值的绝对值为c[i], 即相当于每次加上或者减去这个位置的数时我们都取一次绝对值。
因为这个题目给出的数据范围是小于80, 所以我们可以直接用类似打表的方法, 让d[i][j][k]表示当走到 i 行 j 列时绝对值 k 是否存在。这样每当走到 (i, j)位置时, 就从0到maxn (k可能的最大值)遍历k, 如果 d[i-1][j][k] 或者 d[i[[j-1][k] 存在, 那么就让 d[i][j][abs(k + c[i]) =1, d[i][j][abs(k-c[i]) = 1。最后从0开始遍历d[h][w][k], 找到第一个标记为1的数, 那么此时的 k
就是我们要求的最小值。
这里我给出我的ac代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <stack>
#define fi(i, a, b) for(int i = a; i <= b; ++i)
#define fd(i, a, b) for(int i = a; i >= b; --i)
using namespace std;
typedef long long ll;
const int maxn = 100;
const int maxn2 = 4*80*80+5;
int h, w;
ll a[maxn][maxn], b[maxn][maxn];
int dp[maxn][maxn][maxn2];
int main() {
	cin >> h >> w;
	fi(i, 1, h) {  
		fi(j, 1, w) {
			cin >> a[i][j];
		}
	}
	fi(i, 1, h) {
		fi(j, 1, w) {
			cin >> b[i][j];
			b[i][j] = abs(a[i][j] - b[i][j]);
		}
	}
	dp[1][1][b[1][1]] = 1;
	fi(i, 1, h) {
		fi(j, 1, w) {
			for(int k = 0; k < maxn2; ++k) {
				if (dp[i-1][j][k]) {
					if (k + b[i][j] < maxn2)
						dp[i][j][abs(k+b[i][j])] = 1;
					dp[i][j][abs(k-b[i][j])] = 1;
				}
				if (dp[i][j-1][k]) {
					if (k + b[i][j] < maxn2)
						dp[i][j][abs(k+b[i][j])] = 1;
					dp[i][j][abs(k-b[i][j])] = 1;
				}
			}
		}
	}
	int mi = maxn2;
	fi(i, 0, maxn2-1) {
		if(dp[h][w][i]) {
			mi = i;
			break;
		}
	}
	cout << mi << endl;
	return 0;
}

K题

题目链接

这道题是一个简单的博弈题, 就是给你一颗树, 然后指定一个节点为终点, 两个人从叶子节点开始拿, 谁先拿到这个终点的节点谁胜利。
这道题我们就先统计一下连着这个终点的其他节点的个数cnt, 如果cnt <= 1, 即这个终点就是一个叶子节点, 那么谁先手谁赢, 当cnt >= 2时, 那么我们不难发现, 最后一定会有一个人遇到如图的情况
在这里插入图片描述

那么此时谁先拿谁输, 那么我们可以用剩下的n-3个节点来看谁先到达这种情况, 则当(n-3)%2 == 1时后手会先遇到这种情况, 先手赢, 反之后手赢。

M题

这道题就是说给你 4种括号序列 cnt1 = “((”, cnt2 = “()”, cnt3 = “)(”, cnt4 = “))”,让你求完美的括号序列,就是"("和”)“的数量相同, 且序列中前i给字符中”(“的数量大于等于”)“的数量, 即”(())“是满足的, 而”)(()“则不满足。
给出你cnt1~cnt4的序列的数量, 问你把这些序列全部用上能否组成一个完美的括号序列, ““这种没有字符的情况也符合。
那么我们很容易就可以看出来cnt1 和 cnt4 一定是成对存在的, 如果cnt1 != cnt4那么一定不能组成完美序列, 而cnt3 可以组成”)()()()(“这样的序列, 可以看到, 序列左边需要一个”(” , 右边需要一个”)"才能组成完美的序列, 而能够提供这两个括号, 并且不产生其他影响的就是cnt1 和 cnt4 , 即, 当cnt3 的数量大于0时, 那么cnt1 和 cnt4 的数量至少为1, 否则无法组成完美括号序列, 而cnt2本身就是完美序列, 对最终结果没有影响, 所以不用管它。
即满足 cnt1 == cnt4 && (!cnt3 || (cnt3 && cnt1 >= 1 && cnt4 >= 1) 条件时, 可以组成完美序列。

总结

以上题目就是我们比赛当天做出来的题目(虽然H没能及时通过), 我们做出来的这几道题, 难度都不是很大, 而对于有难度的题目我们又没有更多时间去思考, 导致我们做题的效率并不是很高, 而且, 我们队基本是跟着榜单来做题的, 以至于我们在很大程度上落于人后。所以之后队内任务的分配问题我们还是要好好去考虑的 事实上最大的原因还是我们队太菜了 。总之之后我们还是要多做题, 队内多磨合一下争取找到适合我们队的做题方式, 希望可以在之后的比赛中取得一定的成绩。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值