2022 码蹄杯 部分题解 白银

MC0116 水往低处流 码题集 

 

 这道题第一反应是对每个点进行dfs或者bfs,暴力标记所有的点,但是复杂度太高,看了题解之后,发现一种转化的方法。

遍历所有的点,当他是上下左右中最大的,其肯定是要挑一次水。

给出我的方法,老规矩,用哨兵,减少边界检查。

#include<iostream>
#include<map>
#include<string>
#include<vector>
#include<algorithm>

using namespace std;

vector<vector<int>> orgion;
int sizeOrgion;

int res = 0;

void dfs(int x,int y) {

	int eight = orgion[x][y];

	if (eight >= orgion[x + 1][y]
		&& eight >= orgion[x][y + 1]
		&& eight >= orgion[x - 1][y]
		&& eight >= orgion[x][y - 1]) {
		res++;
	}

	
}


int main()
{
	cin >> sizeOrgion;
	sizeOrgion += 2;

	orgion = vector<vector<int>>(sizeOrgion, vector<int>(sizeOrgion, 0));

	for (int i = 1; i < sizeOrgion - 1; i++) {
		for (int j = 1; j < sizeOrgion - 1; j++)
			cin >> orgion[i][j];
	}

	for (int i = 1; i < sizeOrgion - 1; i++) {
		for (int j = 1; j < sizeOrgion - 1; j++)
			dfs(i, j);
	}
	cout << res << endl;
	
}

MC0136函数的幂Ⅱ

 

 

 

这种题,可以用递归试试,但会超时。主要还是数学方法的转化,求出Cn和Cn-1的关系式,循环求出题目即可。证明: 

这里有个余数的结论,可以证明一下。 

代码

#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<stack>
#include<set>
using namespace std;



int C, D;

int main()
{
	int a, b;
	cin >> a >> b >> C >> D;
	a--;
	while (a--) {
		int C1 = C * C%10;
		int D1 = D * (C + 1)%10;
		C = C1;
		D = D1;
	}
	cout << (C * b + D) % 10 << endl;

}

 MC0138吃外卖

 

 

 

 没啥好说的,记录一下优先级队列的使用。

#include<iostream> 
#include<queue>
using namespace std;

int main()
{
    priority_queue<int> pq;
    int n, m;
    cin >> n >> m;
    while (m--) {
        int temp;
        cin >> temp;
        pq.push(temp);
    }
    int res = 0;
    while (n--) {
        int temp = pq.top();
        res += temp;
        pq.pop();
        pq.push(temp - 1);
    }
    cout << res << endl;

}

 MC0148射线的交

 

 最妙的地方在于

1、用正数负数表示上下 左右两类方向,后面可以通过符号判断是否相乘

2、a可能有两种方向,通过swap来保证其只有一种

#include<iostream> 
#include<vector>
#include<string>
#include<algorithm>
using namespace std;

struct Point {
	int x;
	int y;
	int direction;
};

int getDir(char a) {
	switch (a)
	{
	case 'U':
		return 1;
	case 'L':
		return -1;
	case 'D':
		return 2;
	case 'R':
		return -2;
	default:
		break;
	}
	return '0';
}

int main()
{
	int n; cin >> n;
	vector<Point> orgion(n);
	for (int i = 0; i < n; i++) {
		char temp;
		cin >> orgion[i].x >> orgion[i].y>>temp;
		orgion[i].direction = getDir(temp);
		
	}
	int res = 0;
	for (int i = 0; i < n; i++) {
		for (int j = i+1; j < n; j++) {
			Point a = orgion[i];
			Point b = orgion[j];

			if (a.direction >0)
				swap(a, b);

			if (a.direction * b.direction < 0) {
				if (a.direction == -2 && b.x >= a.x && ((b.direction == 1 && a.y >= b.y) || (b.direction == 2 && a.y <= b.y)))
					res++;
				else if (a.direction == -1 && b.x <= a.x && ((b.direction == 1 && a.y >= b.y) || (b.direction == 2 && a.y <= b.y)))
					res++;
			}
		}
	}

	cout << res << endl;
}

 MC015023划分

 

 有组合数学那味道了,乍一看有点懵,但是解法还是暴力枚举。

1、求出所有的钱数综合sum,2的个数cn2,3的个数cn3

2、当sum为奇数的时候,返回false

3、sum=sum / 2

4、遍历所有2的可能,当算出3的个数小于等于cn3,即可表示出一堆的方法

5、剩下的一堆就是sum/2了

#include<iostream> 
#include<vector>
#include<string>
#include<algorithm>
using namespace std;


int main()
{
	int cn2 = 0, cn3 = 0,sumAll=0;
	int n; cin >> n;
	while (n--) {
		int temp; cin >> temp;
		(temp == 2) ? cn2++ : cn3++;
		sumAll += temp;
	}

	if (sumAll % 2 == 1)
	{
		cout << "NO" << endl;
		return 0;
	}

	sumAll /= 2;
	for (int i = 0; i <= cn2; i++) {
		int tempSum = sumAll - i * 2;
		if (tempSum < 0)
			break;

		if (tempSum % 3 == 0 && tempSum / 3 <= cn3) {
			cout << "YES" << endl;
			return 0;
		}
	}
	cout << "NO" << endl;
	return 0;
}

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
USACO2022金组是国际在线判题系统USACO的最高级别,题目难度较高,在该比赛中取得好成绩是一项巨大的成就。以下是对该比赛的一些题目解析。 第一题:“交通计划” 题目要求:给定一个n个节点的有向图,每条边有一个长度,希望添加最少的边使得所有节点连通,求最小生成树的权值和。 解析:该题可以使用Kruskal算法求解,将每条边按权值从小到大排序,再依次加入,判断加入的边是否会形成环,若形成则不加入,直到所有节点连通为止。此时Kruskal算法得到的最小生成树的权值和即为所求。 第二题:“点火计划” 题目要求:给定一个n个节点的有向图,每条边有一个权值和一个点火时长,每个节点有一个点火启动时刻和时刻结束时刻,希望从其中选出一些边点火,使得所有节点都可从点火的边出发到达,且所选点火边的总点火时长最小。 解析:该题可以使用最小费用最大流算法求解。将每条边看做一个容量为1,费用为点火时长的边,源点向节点的点火边容量为1,费用为0的边,节点的点火边向汇点的容量为1,费用为0的边,对这个网络进行最小费用最大流即可得到所选边的总点火时长最小。 第三题:“美味佳肴” 题目要求:给定n个菜品,每个菜品有它的权值和两个类别,希望选出k个菜品,使得选出的菜品数量在每个类别中都不超过$\frac{k}{3}$个,且所选菜品的权值和最大。 解析:该题可以使用动态规划求解。设$f[i][j][k]$表示前i个菜品中,选择j个一类菜品,选择k个二类菜品的最大权值和,状态转移方程为$f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][k]+a[i],f[i-1][j][k-1]+b[i])$,其中a[i]为i号菜品的权值,若为一类则为该权值,否则为0,b[i]为i号菜品的权值,若为二类则为该权值,否则为0。最终答案为$f[n][$k/3$][$k/3$]。 以上是对USACO2022金组的部分题目的解析,USACO比赛是全球范围内的计算机竞赛,竞争非常激烈,能够在该比赛中脱颖而出是一项非常棒的成就。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值