上海市计算机学会月赛 2022年5月月赛丙组

上海市青少年算法竞赛月赛2022年5月月赛丙组

    • 三数排序
    • 珠玑妙算(一)
    • 打印金字塔
    • 最远城市距离
    • 最大割


三数排序

内存限制: 256 Mb 时间限制: 1000 ms

题目描述
给定三个整数 a , b , c a,b,c a,b,c,请将它们以从小到大的顺序排序后输出。

输入格式
单独一行:三个整数表示 a , b , c a,b,c a,b,c

输出格式
单独一行:表示按升序排列后的三个数。

数据范围
− 1000 ≤ a , b , c ≤ 1000 -1000\leq a,b,c\leq 1000 1000a,b,c1000

样例数据

输入:
6 4 2
输出:
2 4 6

输入:
1 1 1
输出:
1 1 1

简简单单排序题,直接sort(虽然只有三个数)

#include
#include
using namespace std;
int a[3];
int main() {
	cin >> a[0] >> a[1] >> a[2];
	sort(a, a + 3);
	cout << a[0] << " " << a[1] << " " << a[2];
	return 0;
}

珠玑妙算(一)

内存限制: 256 Mb 时间限制: 1000 ms
题目描述
珠玑妙算(Mastermind)是一种猜谜游戏。

在游戏开始前,系统会生成一个十进制的四位整数(每一位数字都不相同)作为谜底。玩家需要提供一个十进制的四位整数(每一位数字也都不相同)作为解答。

对于给定的解答,请统计谜底中有多少既被猜中了数字也被猜中了位置(称这种情况为完全猜中),有多少只猜中了数字但没猜中位置(称这种情况为部分猜中)。

输入格式
第一行:一个四位整数 a a a 表示谜底。
第二行:一个四位整数 b b b 表示解答。

输出格式
第一行:单个整数,表示完全猜中的数量;
第二行:单个整数,表示部分猜中的数量。

样例数据

输入:
5678
8671
输出:
2
1
说明:
6与7为完全猜中,8为部分猜中

先将数字每一位保存到数组,一开始保存时相同就是位置数组都相同;
之后再判断数字相同位置不同的;

#include
using namespace std;
int nums_a[4], nums_b[4], cnt[2] = {0, 0};
int i, j, a, b, len;
int main() {
	cin >> a >> b;

	for (i = 0; i < 4 ; ++i) {
		nums_a[i] = a % 10, a /= 10;
		nums_b[i] = b % 10, b /= 10;

		if (nums_a[i] == nums_b[i])
			++cnt[0];
	}

	for (i = 0; i < 4 ; ++i)
		for (j = 0; j < 4 ; ++j)
			if (nums_b[j] == nums_a[i])
				++cnt[1];
	cout << cnt[0] << endl << cnt[1] - cnt[0];	// 减去重复
	return 0;
}

打印金字塔

内存限制: 256 Mb 时间限制: 1000 ms
题目描述
给定一个整数 n n n,请打印一个具有 n n n 层结构的三角形金字塔,例如当 n = 3 n=3 n=3 时,打印如下图形:

     /\ 
    /__\
   /\  /\
  /__\/__\
 /\  /\  /\
/__\/__\/__\

输入格式
单个整数:表示 n n n

输出格式
根据题意输出层次为 n n n 的三角形金字塔。

数据范围
1 ≤ n ≤ 30 1\leq n\leq 30 1n30

样例数据
输入:
3
输出:

     /\  
    /__\
   /\  /\ 
  /__\/__\
 /\  /\  /\
/__\/__\/__\

输入:
8
输出:

               /\
              /__\
             /\  /\
            /__\/__\
           /\  /\  /\
          /__\/__\/__\
         /\  /\  /\  /\
        /__\/__\/__\/__\
       /\  /\  /\  /\  /\
      /__\/__\/__\/__\/__\
     /\  /\  /\  /\  /\  /\
    /__\/__\/__\/__\/__\/__\
   /\  /\  /\  /\  /\  /\  /\
  /__\/__\/__\/__\/__\/__\/__\
 /\  /\  /\  /\  /\  /\  /\  /\
/__\/__\/__\/__\/__\/__\/__\/__\

找规律,打空格,奇数打印左边,偶数打印右边。

#include 
using namespace std;
int i, j, k, l, n, m, x = 1;
char t = '\\';	// 转义字符,需要两个
int main() {
	cin >> n;
	n *= 2, m = n;
	for (i = 0; i < n ; ++i) {
		--m;
		for (j = 0; j < m ; ++j)
			cout << " ";
		if (i % 2 == 0) {
			for (k = 0; k < x ; ++k) {
				if (k == 0)
					cout << "/" << t;
				else
					cout << "  /" << t;	
			}
			cout << endl;
		} else {
			for (k = 0; k < x ; ++k)
				cout << "/__" << t;
			++x, cout << endl;
		}
	}
	return 0;
}

最远城市距离

内存限制: 256 Mb 时间限制: 1000 ms
题目描述
大城市的道路是相互平行或垂直的,如果在城市的道路上行走,不能用点与点之间的直线距离计算长度,而是应该定义两个点(设坐标分别为 ( x , y ) (x,y) (x,y) ( x ′ , y ′ ) (x',y') (x,y)) 的城市距离为 ∣ x − x ′ ∣ + ∣ y − y ′ ∣ |x-x'|+|y-y'| xx+yy,给定 n n n 个点的坐标,请从中寻找两个点,使得它们的城市距离达到最大,并输出这个最大值。

输入格式
第一行:单个整数 n n n
第二行到第 n + 1 n+1 n+1 行:每行有两个整数 x i x_i xi y i y_i yi ,表示一个点的坐标。

输出格式
单个整数:表示最大的城市距离。

数据范围

  • 对于 30 % 30\% 30% 的数据, 2 ≤ n ≤ 5 , 000 2\leq n\leq 5,000 2n5,000
  • 对于 60 % 60\% 60% 的数据, 2 ≤ n ≤ 50 , 000 2\leq n\leq 50,000 2n50,000
  • 对于 100 % 100\% 100% 的数据, 2 ≤ n ≤ 500 , 000 2\leq n\leq 500,000 2n500,000
  • − 500 , 000 , 000 ≤ x i , y i ≤ 500 , 000 , 000 -500,000,000\leq x_i,y_i\leq 500,000,000 500,000,000xi,yi500,000,000

样例数据
输入:
4
0 0
0 1
1 3
3 2
输出:
5
说明:
(0,0)与(3,2)的城市距离是最大的

递推,类似于曼哈顿距离化为切比雪夫距离求极差

#include 
using namespace std;
int i, n, x, y, max1, min1 = 2e9, max2, min2 = 2e9;
int main() {
    cin >> n;
    for (i = 0; i < n ; ++i) {
        cin >> x >> y;
        max1 = max(max1, x + y);
        min1 = min(min1, x + y);
        max2 = max(max2, x - y);
        min2 = min(min2, x - y);
    }
    cout << max(max1 - min1, max2 - min2);
}

最大割

内存限制: 256 Mb 时间限制: 1000 ms
题目描述
给定一张有 n n n 个点、 m m m 条边的无向图,如果有一种划分,能将图上的所有点不重复不遗漏地分割成两个部分(记为 S S S S ˉ \bar{S} Sˉ),且这两部分都不是空集,则称 ( S , S ˉ ) (S,\bar{S}) (S,Sˉ) 是图的一个割(Cut)。
对于一个割来说 ( S , S ˉ ) (S,\bar{S}) (S,Sˉ),图上有多少边跨越这个割,这个割的大小就是多少。所谓跨越,就是指某条边的一端在 S S S,另一端在 S ˉ Sˉ Sˉ。对于给定的图,请找到一个最大的割,并输出这个割的大小。

输入格式
第一行:两个整数表示 n n n m m m
第二行到第 m + 1 m+1 m+1 行:每行两个整数 u u u v v v 表示一条边的两个端点,保证 u ≠ v u\neq v u=v,注意同一对点之间可能有多条边,这些边应被看做是不同的边。

输出格式
单个整数:表示最大割的大小。

数据范围

  • 对于 50 % 50\% 50% 的数据, 2 ≤ n ≤ 16 2\leq n\leq 16 2n16
  • 对于 100 % 100\% 100% 的数据, 2 ≤ n ≤ 24 2\leq n\leq 24 2n24
  • 1 ≤ m ≤ 10000 1\leq m\leq 10000 1m10000

样例数据
输入:
3 5
1 2
2 3
3 1
1 3
2 3
输出:
4
说明:
将图割成{1,2}与{3},1与3之间有两条边,2与3之间也有两条边。
输入:
4 2
1 2
3 4
输出:
2
说明:
将图割成 {1,3} 与 {2,4} 时割最大。注意与最小割的区别,这个例子中的最小割为0(因为 {1,2} 与 {3,4} 不连通)

深搜确定集合两个集合中的元素,使用二维数组标记

#include 
using namespace std;
int n, m, g[25][25], v[25], ans;
void dfs(int x, int num, int step)
{
    for (int i = 1; i <= n; i++)
        if (v[i])
            num -= g[x][i]; //在T内
        else
            num += g[x][i]; //在S内
    ans = max(ans, num);
    if (step >= n)
        return;
    for (int i = x + 1; i <= n; i++)
    {
        v[i] = 1;
        dfs(i, num, step + 1);
        v[i] = 0;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        ++g[u][v], g[v][u] = g[u][v]; //无向边
    }
    v[1] = 1; //将点1放入T
    dfs(1, 0, 1);
    cout << ans;
    return 0;
}

你可能感兴趣的:(上海市计算机学会月赛题解,算法,c++)