9.19-9.26算法总结

1、Splitting Items

1200分,已经涉及算法了,这里写一点对于算法我自我感觉,我感觉算法是一种通过计算机逻辑的简便实现,人平常好像很难想到,学习之后感觉有点熟能生巧的意思,某种场景用某种算法就是捷径。

问题自述

AB两个人分东西,每件东西都有自己的价格,最后用A的物品总价减去B的物品总价,两人都想自己拿更值钱的东西,A先拿,但B可以在开始前在总金额k范围内增加某些物品的价格,请问B要怎么做才能让自己赚的多

输入输出要求

输入测试用例数t

输入物品总数n和改变范围k

输入n物品各自的价格

输出A-B的值(要求尽可能小

代码实现

#include<iostream>
using namespace std;
int main() {
	int t, n, k, a[200001];

	cin >> t;
	while (t--) {
		int total_a = 0;
		int	total_b = 0;
		cin >> n >> k;
		for (int i = 0; i < n; i++) {
			cin >> a[i];
		}

		for (int j = 0; j < n - 1; j++) {
			for (int f = 0; f < n - j - 1; f++) {
				if (a[f] < a[f + 1]) {
						int num = a[f];
						a[f] = a[f + 1];
						a[f + 1] = num;
				}
			}
		}
		for (int x = 0; x <= n-1; x = x + 2) {
			total_a += a[x];
		}
		for (int y = 1; y <= n-1; y = y + 2) {
			total_b += a[y];
		}
		if (total_a - total_b > k) {
			cout << total_a - total_b - k << endl;
		}
		else {
			cout << 0 << endl;
		}
	}
	return 0;
}

实际上这个代码无法实现,我的逻辑完全错了,对于基础库也用的不够熟练,分析正确代码后得出原因:对于奇数种可能时,两者选择的商品数不同,不能用简单的加和来处理差距,我的这种方法忽略了顺序问题,只对结果进行考虑是不对的。

正确代码

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
#define int long long
int a[N],n,k,T;
signed main(){
	cin>>T;
	while(T--){
		cin>>n>>k;
		for(int i=1;i<=n;i++) cin>>a[i];
		sort(a+1,a+1+n);
		int ans=0;
		for(int i=n;i>=1;i-=2){
			if(i==1){
				ans+=a[i];
				break;
			}
			int dlt=a[i]-a[i-1];
			int c=min(dlt,k);
			dlt-=c,k-=c,ans+=dlt;
		}
		cout<<ans<<"\n";
	}
}
/*FOOTNOTE
*/

思路:首先完成排序后根据目的平衡每个相邻数字之间的差值,由于每个人都倾向于拿更有价值的物品,所以从最大的两个数开始平衡,直到将k的值用完,并且当商品数为奇数时,这最后一个商品无法平衡,需要直接加到结果中。

2、osu!mania

800分

问题自述

从n行4列中找出#的位置,并从最后一行到高输出

代码实现

#include<iostream>
using namespace std;
string s[5000];
void solve() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> s[i];
	}
	for (int i = n; i >= 1; i--) {
		cout << s[i].find("#") + 1 << endl;
	}
}
int main() {
	int t;
	cin >> t;
	while (t--) {
		solve();
	}
}

建立数组,每个数组代表一行字符,在其中直接找#字符,然后+1即为按照1234排列的具体位置

#include<iostream>
#include<vector>

using namespace std;

int main(){
int t;cin>>t;
while(t--){
int n;cin>>n;
vector<string>vec(n);
for(int i = 0;i<n;i++)cin>>vec[i];
for(int i = n-1;i>=0;i--){
for(int c = 1;c<=4;c++){
if(vec[i][c-1]=='#')cout<<c<<' ';
}
}
cout<<endl;
}
}

利用vector动态数组帮助求解,建立字符串型vec动态数组,两个循环分别遍历每一行的内容和每一行中的#,利用4列直接输出#的位置

3、Index and Maximum Value

问题自述

挑一个数组,出n个范围,当+时,把数组中再该范围内的数加1,当-时,减1,最后输出这个数组中的最大值

代码实现

#include<iostream>
using namespace std;
int T, n, m, a[100001], mx, l, r;
char op;
int main() {
	cin >> T;
	while (T--) {
		cin >> n >> m;
		for (int i = 1; i <= n; i++) {
			cin >> a[i];
		}
		for (int j = 0; j < n - 1; j++) {
			for (int f = 0; f < n - j - 1; f++) {
				if (a[f] < a[f + 1]) {
					int num = a[f];
					a[f] = a[f + 1];
					a[f + 1] = num;
				}
			}
		}
		int mx = a[0];
		while (m--) {
			cin >> op >> l >> r;
			if (l <= mx && mx <= r) {
				if (op == '+') mx++;
				if (op == '-') mx--;
			}
			cout << mx << ' ';
		}
	}		
	return 0;
}

先利用冒泡排序对数组进行排序,然后直接找出该数组中的最大值,因为任何值加都只可能和最大值一样大,如果大于最大值那么最大值也应该在范围内,如果最大值减少到第二大的值还没停止,那第二大的值会一同减少,则最大的仍时最大值,故对最大值进行操作即可

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int T,n,m,a[N];
int main(){
	cin>>T;
	while(T--){
		cin>>n>>m;int mx=0;
		for(int i=1;i<=n;i++)cin>>a[i],mx=max(mx,a[i]);
		char op;
		for(int l,r;m--;)cin>>op>>l>>r,l<=mx&&mx<=r&&(mx+=op=='+'?1:-1),cout<<mx<<' ';
		puts("");
	}
	return 0;
}

思路类似,但这个通过每个输入的值与之进行判断之后就可以找出最大值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值