CSDN编程竞赛 周赛第11期 满分题解

12 篇文章 0 订阅
8 篇文章 0 订阅

1、圆小艺(简单数学)

题目

最近小艺酱渐渐变成了一个圆滑的形状-球!! 小艺酱开始变得喜欢上球! 小艺酱得到n个同心圆。 小艺酱对着n个同心圆进行染色。 相邻的圆范围内不能有相同的颜色。相隔一层的圆颜色相同。 小艺酱想知道圆最外层的那种颜色全部染了多少?

题解

计算多个圆环的面积,最内层可能是圆或圆环。
排序后从大到小计算圆面积,加一次,减一次……
可能有double精度问题,改了几次才通过。

代码


#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include<cmath>

using namespace std;

long double solution(int n, std::vector<int> &vec) {
    long double result;
// TODO:
    result = 0.0;
    sort(vec.begin(), vec.end());
    int sz = vec.size();
    const long double pi = acos(-1.0);
    long long res = 0;
    for (int i = sz - 1, j = i - 1; i >= 0; i -= 2, j -= 2) {
        res += (long long) (vec[i]) * vec[i];
        if (j >= 0) {
            res -= (long long) (vec[j]) * vec[j];
        }
    }
    result = res * pi;
    return result;
}

int main() {
    int n;
    std::vector<int> vec;
    std::cin >> n;
    std::string line_0, token_0;
    getline(std::cin >> std::ws, line_0);
    std::stringstream tokens_0(line_0);
    while (std::getline(tokens_0, token_0, ' ')) {
        vec.push_back(std::stoi(token_0));
    }
    long double result = solution(n, vec);
    printf("%.3f\n", (double) result);
    return 0;
}

2、K皇把妹 (简单枚举)

题目

存在n个节点,目标节点在m。 每个节点有自己的权值a。 在权值k内(含k值)选择一个权值非0节点且与目标节点距离最近。 节点i与节点j的距离为abs(i-j)。

题解

从目标节点向两侧等距枚举,找到首个满足要求的节点,即可立即返回距离。

代码


#include <iostream>
#include <string>
#include <sstream>
#include <vector>

int solution(int n, int m, int k, std::vector<int> &vec) {
// TODO:
// 0 m-1 n-1
    for (int i = m - 2, j = m; i >= 0 || j < n; i--, j++) {
        if (i >= 0) {
            if (vec[i] != 0 && vec[i] <= k) {
                return m - 1 - i;
            }
        }
        if (j < n) {
            if (vec[j] != 0 && vec[j] <= k) {
                return j - m + 1;
            }
        }
    }
    return -1;
}

int main() {
    int n;
    int m;
    int k;
    std::vector<int> vec;
    std::cin >> n;
    std::cin >> m;
    std::cin >> k;
    std::string line_0, token_0;
    getline(std::cin >> std::ws, line_0);
    std::stringstream tokens_0(line_0);
    while (std::getline(tokens_0, token_0, ' ')) {
        vec.push_back(std::stoi(token_0));
    }
    int result = solution(n, m, k, vec);
    std::cout << result << std::endl;
    return 0;
}

3、筛选宝物(背包问题,简单动态规划)

题目

已知存在n个宝物,每个宝物都有自己的质量m和价值v,在考虑选择宝物时只能选择总质量小于等于M的方案,请问在最优方案下选择宝物,能获取到最大价值V是多少?

题解

经典背包问题。
dp[当前枚举到的质量] = dp[当前枚举到的质量-某物品的质量]+某物品的价值。

代码


package main

import "fmt"

func solution(n int, M int, arr [][2]string) {
	// TODO: 请在此编写代码
	var dp []int
	for i := 0; i <= M; i++ {
		dp = append(dp, 0)
	}
	for _, line := range arr {
		var m, v int
		fmt.Sscanf(line[0], "%d", &m)
		fmt.Sscanf(line[1], "%d", &v)
		for j := M; j >= m; j-- {
			if dp[j] < dp[j-m]+v {
				dp[j] = dp[j-m] + v
			}
		}
	}
	fmt.Println(dp[M])
}
func main() {
	var temp_arr [2]int
	for i := 0; i < 2; i++ {
		fmt.Scan(&temp_arr[i])
	}
	n := temp_arr[0]
	M := temp_arr[1]
	arr := make([][2]string, n)
	for i := 0; i < n; i++ {
		for j := 0; j < 2; j++ {
			fmt.Scan(&arr[i][j])
		}
	}
	solution(n, M, arr)
}

4、圆桌(贪心)

题目

有N个客人与足够多张的圆桌。主人安排每位客人坐在一个圆桌边,但是每位客人希望自己左右边上分别有一些空座位,不然会觉得害羞。注意,如果一个客人所在的圆桌只有他一个人,那么他左边的空座位数量就是他右边的空座位数量。 试问主人需要准备多少个座位,才能让每个客人舒适的坐下。

题解

简单试算可以发现,当有1个人时,他左边座位数和右边座位数的较大值被计入答案。
当不止一个人时,除了客人本身之外,左右座位数将被一一配成若干对,每对较大值被计入答案。
因此,配对方式应该让一侧的值“覆盖”另一侧的较大值,避免其被计入答案。
所有人的左右座位数总有一个最大的,将它用于“覆盖”另一侧最大的数。
因此结果就是左右侧分别排序后,相同次序的数配成一对,较大数计入答案。

代码


package main

import "fmt"
import "sort"

func solution(n int, arr [][2]string) {
	// TODO: 请在此编写代码
	var a, b []int
	for _, line := range arr {
		var x int
		fmt.Sscanf(line[0], "%d", &x)
		a = append(a, x)
		fmt.Sscanf(line[1], "%d", &x)
		b = append(b, x)
	}
	sort.Ints(a)
	sort.Ints(b)
	var res int64
	res += int64(n)
	for i, aa := range a {
		bb := b[i]
		if aa > bb {
			res += int64(aa)
		} else {
			res += int64(bb)
		}
	}
	fmt.Println(res)
}
func main() {
	var n int
	fmt.Scan(&n)
	arr := make([][2]string, n)
	for i := 0; i < n; i++ {
		for j := 0; j < 2; j++ {
			fmt.Scan(&arr[i][j])
		}
	}
	solution(n, arr)
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值