2021-07-22

暑假集训第三篇博客
先来个小总结:暑期集训已经开始了一个礼拜,也意味着过去了1/5,感觉这几天学到了不少,但是应该能提高效率,在单位时间内学到更多的知识。

2021年山东省程序设计大赛(2021年7月21日 12:00 - 17:00,在gym上vp)
对于山东省赛,这场比赛我们队伍能出四题,有点拉跨。对于本人蒟蒻来言,自己的补题上限是四题,希望以后学了更多的算法能补更多吧。

G .Grade Point Average
本题题意:给你n个数,计算这n个数的平均数,并保留k位小数,k的范围是1-1e5
思路:本题主要是模拟除法运算法则,先求出商,然后再用余数乘10再除以n,再求余数 乘以10除以n的余数,再一直进行相同的操作,一直求到k位小数就行。

#include <bits/stdc++.h>

using namespace std;

int n, k;
int a[100010];
int yu[100010];
long long sum = 0;
int main()
{
	cin >> n >> k;
	for(int i = 1; i <= n; i ++ ) 
	{
		cin >> a[i];
		sum += a[i];
	}
	int shang =  sum / n;
	int yu = sum - shang * n;
	cout << shang << ".";
	while(k -- )
	{
		int ji = yu * 10;
		int shang1 = ji / n;
		cout << shang1;
		yu = (ji - shang1 * n) ; 
	}
	cout << endl;


	return 0;
}

D.Dyson Box
本题题意:有一个边长的范围为1-2e5单位的正方形,正方形可以理解为平面直角坐标系,给你一个整数n代表箱子的个数,接下来的n行,为箱子的右上角的坐标,有两种操作,一种是将所有的箱子全部往左边移动,第二种是,将所有的箱子全部往下边移动,问你,分别在这两种操作的情况下,形成的图形的周长是多少。
模拟样例:

输入:
4
1 2
3 2
2 1
4 1
输出
4 4
8 6
8 8
10 8

样例1
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
思路:本题可以先通过画图模拟样例,总结规律:
分析垂直操作后的答案(水平分析也一样):
当没有边重合的时候,就是ans = n * 4,然后如果箱子出现的这一列中之前有箱子,那么箱子 肯定下面这条边要重合,所以,答案变成ans -= 2,然后如果在这个箱子出现之前,左边或者右边的箱子数目比当前之一列的箱子数目要多,那么肯定左边或者右边两边会重合,这时候答案变成ans -= 2

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;

int n, x, y;
int v[N], h[N];//每一列的箱子数和每一行的箱子数

int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin >> n;
	int ans1 = 0, ans2 = 0;
	while(n -- )
	{
		cin >> x >> y;
		ans1 += 4, ans2 += 4;//水平,垂直
		if(h[x]) ans1 -= 2;
		if(v[y]) ans2 -= 2;
		if(x > 1 && h[x] < h[x - 1]) ans1 -= 2;
		if(y > 1 && v[y] < v[y - 1]) ans2 -= 2;
		if(h[x] < h[x + 1]) ans1 -= 2;
		if(v[y] < v[y + 1]) ans2 -= 2;
		h[x] ++, v[y] ++;
		cout << ans1 << " " << ans2 << endl; 
	}
	return 0;
}

M.Matrix Problem
题意:给你个C矩阵(只包含01),让你创造两个矩阵A,B,条件:
(1)当C矩阵的某个位置是1,A矩阵和B矩阵的那个位置也是是1,
同样,C矩阵不是1的地方,AB矩阵那个位置不能同时为1.
(2)所求的AB矩阵的从任意一个1开始,可以上下左右移动,必须要不经过0的情况下经过所有的1。
思路:
对于A矩阵:我们令它的奇数行从第一列到m - 1列为1,令它的第一列为1.
对于B矩阵:我们令它的偶数行从第二列到第m列为1,令它的第m列为1.
看完就明白,这种方法满足题意

这个代码写的太丑了,看思路吧。。。。

#include <bits/stdc++.h>

using namespace std;

const int N = 520;
int n, m;
char a[N][N], b[N][N], c[N][N];

int main()
{
	cin >> n >> m;
	for(int i = 0; i < n; i ++ ) cin >> a[i];

	for(int i = 0; i < n; i ++ )
		for(int j = 0; j < m; j ++ )
			b[i][j] = '0', c[i][j] = '0';

	for(int i = 0; i < n; i ++ )
		for(int j = 0; j < m; j ++ )
			if(a[i][j] == '1')
				 b[i][j] = '1',c[i][j] = '1';

	for(int i = 0; i < n; i += 2)
		for(int j = 0; j < m - 1; j ++ )
			b[i][j] = '1';

	for(int i = 0; i < n; i ++ ) b[i][0] = '1';

	for(int i = 1; i < n; i += 2)
		for(int j = 1  ; j < m ; j ++ )
			c[i][j] = '1';

	for(int i = 0; i < n; i ++ ) c[i][m - 1] = '1';

	
	for(int i = 0; i < n; i ++ )
	{
		for(int j = 0; j < m; j ++ )
		{
			cout << c[i][j];
		}
		cout << endl;
	}
	for(int i = 0; i < n; i ++ )
	{
		for(int j = 0; j < m; j ++ )
		{
			cout << b[i][j];
		}
		cout << endl;
	}
	return 0;
}

H.Adventurer’s Guild
本题考的是动态规划,背包问题。
题意:给你n个怪兽的生命值和耐力值,和一个英雄的生命值和耐力值,击败怪兽要会消耗和怪兽同等的生命值和耐力值,在保证你的生命值不为0的情况下,如何选择怪兽击杀获得最大的收益,其中,英雄的生命值可以转化为耐力值。
思路:和01背包一样,用dp[i][j]表示生命值消耗不超过i,耐力值消耗不超过j的最大收益,有两种情况,一种是英雄的耐力值和生命值都大于怪兽的,if(j >= ms) dp[i][j] = max(dp[i][j] , dp[i - mh][j - ms] + w);另外一种是耐力值不够生命值来凑的:`dp[i][j] = max(dp[i][j] , dp[i + j - mh -ms][0] + w);
代码:

#include <bits/stdc++.h>

using namespace std;

int n, H, S;
long long mh, ms, w;
long long dp[310][310];

int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin >> n >> H >> S;
	// long long dp[i][j] = 0;
	while(n -- )
	{
		cin >> mh >> ms >> w;
		for(int i = H; i > 0; i -- )
		{
			for(int j = S; j >= 0; j -- )
			{
				// long long &dp[i][j] = dp[i][j]; 
				if(i > mh && i + j > mh + ms)	
				{				
					if(j >= ms) dp[i][j] = max(dp[i][j] , dp[i - mh][j - ms] + w);
					else dp[i][j] = max(dp[i][j] , dp[i + j - mh -ms][0] + w);
					// dp[i][j] = dp[i][j];
				}
			}
		}
	}
	cout << dp[H][S] << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值