欢迎拜访 zhaosang的博客|

冬天的睡袋

园龄:1年1个月粉丝:2关注:3

2024 暑假友谊赛-热身1(7.11)zhaosang

A-A
https://vjudge.net/contest/639453#problem/A
为了解决这个问题,我们需要确定将墙上的所有数字转换为数字1的最小成本。将数字i转换成数字j的代价由矩阵c[i][j]给出。
这里有一个循序渐进的方法来解决这个问题:
输入读数:读取成本矩阵c和墙体配置A。
Floyd-Warshall算法:使用Floyd-Warshall算法找到将任意数字i转换为任意数字j的最小成本。这是必要的,因为直接转换成本可能不是最小的;我们可能需要处理中间数字。
计算最小成本:对于墙上的每个数字,使用Floyd-Warshall算法的结果计算将其转换为1的最小成本。
累加成本:累加所有的最小成本得到总最小成本。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
	int H, W;
	cin >> H >> W;
	
	vector<vector<int>> c(10, vector<int>(10));
	for (int i = 0; i < 10; ++i) {
		for (int j = 0; j < 10; ++j) {
			cin >> c[i][j];
		}
	}
	
	for (int k = 0; k < 10; ++k) {
		for (int i = 0; i < 10; ++i) {
			for (int j = 0; j < 10; ++j) {
				c[i][j] = min(c[i][j], c[i][k] + c[k][j]);
			}
		}
	}
	
	vector<vector<int>> A(H, vector<int>(W));
	for (int i = 0; i < H; ++i) {
		for (int j = 0; j < W; ++j) {
			cin >> A[i][j];
		}
	}
	
	long long total_cost = 0;
	for (int i = 0; i < H; ++i) {
		for (int j = 0; j < W; ++j) {
			if (A[i][j] != -1) {
				total_cost += c[A[i][j]][1];
			}
		}
	}
	
	cout << total_cost << endl;
	
	return 0;
}

读出尺寸H和W。 读取代价矩阵c,它表示将数字i转换为数字j的代价。 Floyd-Warshall算法:

该算法用于寻找加权图中所有顶点对之间的最短路径。在这里,它有助于找到将任何数字转换为任何其他数字的最小成本,并考虑可能的中间转换。
计算最小成本:

对于墙上的每个数字(不包括-1),使用Floyd-Warshall算法预先计算的成本计算将其转换为1的最小成本。
合计费用:

将所有单个最小成本相加,得到将墙上所有数字转换为1所需的总最小成本。
该方法保证了找到最优的转换路径并有效地计算出最小的总成本。
B_B
https://vjudge.net/contest/639453#problem/B
要解决这个问题,我们需要找到一个整数 b 使得 ∑i=1N|Ai−(b+i)| 最小。我们可以通过以下步骤来解决这个问题:

理解绝对值函数的性质:绝对值函数 |x−y| 在 x=y 时达到最小值 0。因此,我们需要找到一个 b 使得 Ai 尽可能接近 b+i。

中位数性质:对于一个数组 A,如果我们希望最小化 ∑i=1N|Ai−x|,那么 x 应该是数组 A 的中位数。这是因为中位数是使得绝对值和最小的点。

转换问题:我们可以将问题转换为找到一个 b 使得 ∑i=1N|Ai−(b+i)| 最小。我们可以将 Ai 减去 i 得到一个新的数组 Bi=Ai−i,然后找到 B 的中位数 b。

计算最小值:找到 b 后,计算 ∑i=1N|Ai−(b+i)|。

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

using namespace std;

int main() {
	int N;
	cin >> N;
	vector<long long> A(N);
	for (int i = 0; i < N; ++i) {
		cin >> A[i];
	}
	
	vector<long long> B(N);
	for (int i = 0; i < N; ++i) {
		B[i] = A[i] - (i + 1);
	}
	
	sort(B.begin(), B.end());
	long long b = B[N / 2];
	
long long sadness = 0;
	for (int i = 0; i < N; ++i) {
		sadness += abs(A[i] - (b + (i + 1)));
	}
	
	cout << sadness << endl;
	
	return 0;
}

C_C

https://vjudge.net/contest/639453#problem/C
要解决这道题,先分析特殊情况,如果全部相同输出0,如果n==m,不是全部相同输出1.
然后贪心的思考找到数量最多的数,让这个数的最后一个从后往前遍历,如果不是最后一个再往后遍历一次。往前每次走的步数是m-1.

#include <bits/stdc++.h>
using  namespace std;

using ll =long long;

const ll inf=2e18;
ll n,m;
ll v[10000010];
ll pd[10000010];
ll ma=0;
ll cnt; 
ll res;
bool cmp(ll a,ll b){
	return a>b;
}
 int main(){
	ios::sync_with_stdio(0),cout.tie(0),cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>v[i];
		pd[v[i]]++;
		if(pd[v[i]]>=ma){
			ma=pd[v[i]];
			cnt=v[i];
			res=i;
		}     
	}
	if(ma==n){
		cout<<0;
	}else if(m==n){
		cout<<1;
	}else{
		ll ans=0;
		ll d=res;
		while(1){
			d-=m-1;
			ans++;
			if(d<=1){
				break;
			}
		}
		d=res;
		if(res<n){
			while(1){
				d+=m-1;
				ans++;
				if(d>=n){
					break;
				}
			}
		}
		cout<<ans;
	}
	
	
}
G-G

https://vjudge.net/contest/639453#problem/G
就从前往后遍历一次,记录大于等于m次的连续数字的值和次数,用muitset<int,greater>从大到小保存,如果发现当前的值和上一个不同,把set的元素加出来,如果有大于等于m个,累计次数超过m就跳出。每次加完要清空set。
这里我代码不能特判当n为1的情况,我浪费了半个钟重写。最后加个特判n为1就过了。牢记
代码如下:

#include <bits/stdc++.h>
using namespace std;
using ll =long long;
ll v[1000010];
char t[1000010];
multiset<int,greater<int>>st;
int main(){
	ll n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>v[i];
	}    
	for(int i=1;i<=n;i++){
		cin>>t[i];
	}
	char cnt=t[1];
	ll sum=0;
	ll res=1;
	if(n==1){
		cout<<v[1];
		return 0;
	}
	for(int i=1;i<=n;i++){
		if(i==1)st.insert(v[1]);
		else{
			if(t[i]==cnt&&i<n){
				res++;
				st.insert(v[i]);
			}else{
				if(t[i]==cnt&&i==n){
					res++;
					st.insert(v[i]);	
				}
				if(res>=m){
					int j=1;
					for (set<int>::iterator it = st.begin(); it != st.end(); it++)
					{
						sum+= *it;
						j++;
						if(j>m)break;
					}
					st.clear();
					
				}else{
					
					for (set<int>::iterator it = st.begin(); it != st.end(); it++)
					{
						sum+= *it;
					}
					st.clear();
					
				}
				if(i==n&&cnt!=t[i])sum+=v[i];
				cnt=t[i];
				st.insert(v[i]);
				res=1;
				
			}
		}
	}  
	cout<<sum;
}

本文作者:冬天的睡袋

本文链接:https://www.cnblogs.com/dontian/p/18297097

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   冬天的睡袋  阅读(43)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起