Codeforces Round #542 [Alex Lopashev Thanks-Round] (Div. 2)

学大佬来一波题解。。。。。

A. Be Positive

题意:给你一个数组  a ,  a  里面的每一个数除以一个相同的数  x   , 得到的新的 a 数组 , 若该数组里的正数或负数的个数大于数组长度的一半 , 便输出 x 的值 , 若没有则输出0;

思路 :记录数组里的正数和负数 , 判断他们有没有大于数组长度的一半 , 若有直接输出  1  或  -1   , 若没有输出 0 ;

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e3+8;
int a[maxn];
int main()
{
	int n , num1 = 0 , num2 = 0 , ans , ret , op;
	cin >> n;
	for(int i = 1 ; i <= n ; i++)
	{
		cin >> a[i];
		if(a[i] > 0)
		{
			num1++;
		}
		else if(a[i] < 0)
		{
			num2++;
		}
		else
		{
			continue;
		}
	}
	ans = n/2;
	if(n % 2 != 0)
	{
		ans = n/2+1;
	}

	if(num1 >= ans)
	{
		cout << "1"<<endl;
	}
	else if (num2 >= ans)
	{
		cout <<"-1"<<endl;
	}
	else 
	{
		cout <<"0" << endl;
	}
	return 0;
 } 

B. Two Cakes

题意:有俩个人 , 他们现在要各做一个N层的蛋糕 , 有2*N个房子 , 每个房子里有一层型号的蛋糕 , 蛋糕要从小到大收集。

相邻房子之间的距离为 1  , 俩个人的初始起点都在最左边的房子。问完成蛋糕后俩人走的最短步数是多少。

思路:

A , B 俩个人从最左边开始先找 1 这个房间 ,(A 去了B就要去另一个房间了) ,然后分别往下找,在所有的可能性中找到最少的那个。

将这些房间从小到大排好序(但他们的标号不变),再根据标号的加减确定步数。

例:

标号: 1  2  3  4  5  6  7  8

房间 :4  1  3  2  2  3  1  4

排序后:

标号: 2  7   4   5   3   6   1   8

房间:1   1   2   2   3   3   4   4

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+8;
struct node
{
	int num;
	int op;
}a[maxn];
int cmp(node a , node b)
{
	return a.num < b.num;
 } 
int main()
{
	int n ;
	long long ans = 0;
	cin >> n; 
	for(int i = 1 ; i <= 2*n ; i++)
	{
		cin >> a[i].num;
		a[i].op = i;
	}
	int ret = a[1].op;	

	sort(a+1 , a+n*2+1 , cmp);
//	printf("a[1].op = %d a[2].op = %d\n" , a[1].op , a[2].op);
	
	ans += abs(a[1].op - ret);
	ans += abs(a[2].op - ret);
//	cout <<"ans = "<<ans << endl;
	int x = 0 , y = 0;
	for(int i = 3 ; i <= 2*n; i+=2)
	{
//		cout <<"a[i].op = "<<a[i].op <<endl;
		x =abs(a[i].op-a[i-2].op)  + abs(a[i+1].op-a[i-1].op);
		y = abs(a[i].op-a[i-1].op) + abs(a[i+1].op-a[i-2].op);
//		cout <<"x = "<<x<<"    "<<"y = "<<y <<endl;
		ans += min(x , y);
	}
	cout << ans << endl;
	return 0;
 } 

C. Connect

题意:给你俩个坐标 , 分别是起始坐标和终点坐标,可以上下左右走 ,但遇海洋不能走。再给你一个地图 , 0 为陆地 , 1 为海洋。

最多只能建造一条隧道跨过海洋连接俩个陆地 , 使得可以从起点走到终点。隧道的成本是 (rs−rt)^2+(cs−ct)^2

思路:

找包含起点和终点的俩个连通块,然后暴力找最小成本 , 如果起点和终点在一个连通块中 , 就不需要成本了。

代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int vis[100][100] , Map[100][100] , ans = INF;
char arr[100][100];
int n , r1 , c1 , r2 , c2;
int dis[4][2] = {0 , 1 , 1 , 0 , 0 , -1 , -1 ,0};
struct node
{
	int x;
	int y;
	node(int x , int y):x(x) , y(y){}
};
int check(int x , int y)
{
	if(x < 0 || y < 0 || x >= n || y >= n || vis[x][y] == 1 || arr[x][y] == '1')
		return 0;
	return 1;
}
int answer(int x1 , int y1 , int x2 , int y2)
{
	return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
void bfs(int x , int y , int k)
{
	queue<node> Q;
	vis[x][y] = 1;
	Q.push(node(x , y));
	while(!Q.empty())
	{
		node p = Q.front();
		Q.pop();
		Map[p.x][p.y] = k;
		for(int i = 0 ; i < 4 ; i++)
		{
			int xx = p.x + dis[i][0];
			int yy = p.y + dis[i][1];
			if(check(xx , yy))
			{
				vis[xx][yy] = 1;
				Q.push(node(xx , yy));
			}
		}
	}
}
int main()
{
	int sum = 0;
	cin >> n >> r1 >> c1 >> r2 >> c2;
	r1--,r2--,c2--,c1--;
	for(int i = 0 ; i < n ; i++)
	{
		cin >>arr[i];
	}
	for(int i = 0 ; i < n ; i++)
	{
		for(int j = 0 ; j < n ; j++)
		{
			if(vis[i][j] == 0 && arr[i][j] == '0')
			{
				bfs(i , j , sum++);
			}
		}
	}
	if(Map[r1][c1] == Map[r2][c2])
	{
		cout <<"0"<<endl;
	}
	else
	{
		for(int i = 0 ; i < n ; i++)
		{
			for(int j = 0 ; j < n ; j++)
			{
				if(arr[i][j] == '0' && Map[i][j] == Map[r1][c1])
				{
					for(int w = 0 ; w < n ; w++)
					{
						for(int s = 0 ; s < n ; s++)
						{
							if(arr[w][s] == '0' && Map[w][s] == Map[r2][c2])
							{
								ans = min(ans , answer(i , j , w , s));
							}
						}
					}
				}
			}
		}
		cout << ans;
	}
	
	return 0;
 } 

D2. Toy Train

题意:有形成圆的N个站点  , 每个站点有0或多个糖果 , 糖果标记了自己要去的目的站。火车从起点循环顺时针开,每经过一个站点都可以带上一个糖果 , 到达目标站可放下该糖果 , 注意 , 在一个站只能带上一个糖果,火车的容量无限大。

俩站点之间火车花费 1 秒 , 搬运糖果的时间不计。求以每个站点为起点时花费的最少时间是多少;

思路:

i 表示起点 , j 表示糖果数最多的站点 , k 表示该站点最后一个糖果的目标站点。

num为糖果数 , dis[i][j] 表示 i 到 j 的步数 

那么就有 ans = (num-1)* n + dis[i][j] + dis[j][k];

循环每个起点 , 以及该起点下循环每个站点 , 以及该站点下每个糖果的目标地,求最小值。

代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f 
using namespace std;
vector<int>V[5080];
int main()
{
	int n , m, a , b , ans  , op;
	cin >> n >> m;
	for(int i = 0 ; i < m ; i++)
	{
		cin >> a >> b;
		V[a].push_back(b);
	} 
	for(int i = 1 ; i <= n ; i++)
	{
		ans = 0;
		for(int j = 1 ; j <= n ; j++)
		{
			op = INF;
			int num = V[j].size();
			if(num == 0)continue;
			for(auto k : V[j])
			{
				op = min(op , (num-1)*n+(j-i+n) %n+(k-j+n)%n);
			 } 
			 ans = max(ans , op);
		}
		cout <<ans <<" ";
	 } 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41593380/article/details/88084476