【學校訓練記錄】10月個人訓練賽3個人題解

qkauto發表於2024-10-17

A:

根據題意我們可知,第一種事件為從1到i的和,第二種事件為從y到i的和故我們可以透過字首和來儲存從i到i+1所化的時間。再遍歷尋找最小值即可

#include <bits/stdc++.h>
#define endl "\n"
#define int long long
using namespace std;

int n, a[1010]; 
void solve(){
	cin >> n;
	for(int i = 1; i <= n-1; i++){
		string s; cin >> s;
		if(s == "Patrik"){
			int x; cin >> x;
			a[i] = x;
		}
		else {
			int x, y; cin >> x >> y;
			a[i] = a[x-1]+y;
		}
	}
	int mins = 1e18;
	for(int i = 1; i <= n-1; i++){
		mins = min(mins, a[i]-a[i-1]);
	}
	for(int i = 1;i <= n-1; i++){
		if(a[i]-a[i-1]==mins){
			cout << a[i]-a[i-1] << ' ' << i << ' ' << i+1 ;
			break;
		}
	}
}
signed main (){
	ios::sync_with_stdio(false);
	cin.tie(nullptr); 
	int T;
//	cin >> T;
	T = 1;
	while (T--) {
		solve();
	}
	return 0;
}

B:

每人一張牌,每人手中的牌有一個權值,若牌與T相同則為找出其權值最大,沒有T就找與第一個人相同且權值最大的即可

#include <bits/stdc++.h>
#define endl "\n"
#define int long long
using namespace std;

int n, m, a[200010], b[200010]; 
void solve(){
	cin >> n >> m;
	int maxs = 0, num = 0;
	for(int i = 1; i <= n; i++) cin >> a[i];
	for(int i = 1; i <= n; i++) cin >> b[i];
	for(int i = 1; i <= n; i++){
		if(a[i]==m && b[i]>maxs){
			maxs = b[i];
			num = i;
		}
	}
	if(!num){
		m = a[1], maxs = b[1], num = 1;
		for(int i = 1; i <= n; i++){
			if(a[i]==m && b[i]>maxs){
				maxs = b[i];
				num = i;
			}
		}
	}
	cout << num;
}
signed main (){
	ios::sync_with_stdio(false);
	cin.tie(nullptr); 
	int T;
//	cin >> T;
	T = 1;
	while (T--) {
		solve();
	}
	return 0;
}

C:

此題根據求和不難想到為二維字首和,而資料量較小,我們可以直接遍歷矩形左上和右下的端點來遍歷每一個矩陣即可

#include <bits/stdc++.h>
#define endl "\n"
#define int long long
using namespace std;

int n, m, k, a[110][110];
void solve(){
	cin >> n >> m >> k;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++){
			char ch; cin >> ch;
			int c = ch-'0';
			a[i][j]= c-a[i-1][j-1]+a[i-1][j]+a[i][j-1];
		}
	}
	int mins = 1e18;
	for(int x = 1; x <= n; x++){
		for(int y = 1; y <= m; y++){
			for(int i = x; i <= n; i++){
				for(int j = y; j <= m; j++){
					int now = a[i][j]-a[i][y-1]-a[x-1][j]+a[x-1][y-1];
					if(now>=k) mins = min(mins, (i-x+1)*(j-y+1));
				}
			}
		}
	}
	if(mins == 1e18) cout << '0';
	else cout << mins;
}
signed main (){
	ios::sync_with_stdio(false);
	cin.tie(nullptr); 
	int T;
//	cin >> T;
	T = 1;
	while (T--) {
		solve();
	}
	return 0;
}

D:

資料量小我們可以直接遍歷每一種範圍內位置的左端點並計算實現不交稅之後的值,求出其最小值

#include <bits/stdc++.h>
#define endl "\n"
#define int long long
using namespace std;

int n,a[1100]; 
void solve(){
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i];
	sort(a+1, a+1+n);
	int sum = 1e18;
	for(int i = a[1]; i <= a[n]; i++){
		int now = 0;
		for(int j = 1; j <= n; j++){
			if(a[j]>i+17){
				now+=(a[j]-i-17)*(a[j]-i-17);
			}
			else if(a[j]<i){
				now+=(i-a[j])*(i-a[j]); 
			}
		}
		sum = min(now, sum);
	}
	cout << sum;
}
signed main (){
	ios::sync_with_stdio(false);
	cin.tie(nullptr); 
	int T;
//	cin >> T;
	T = 1;
	while (T--) {
		solve();
	}
	return 0;
}

E:暫時不會
F:

區間dp透過計算i到i+l的區間內的最優解來依次實現每個區間的最優解,直到大小為整個區間,其中a[i][i+l]為從i開始長度為l的區間的最優解,其中遍歷實現依次將區間內哪兩個操作過的史萊姆合成值最小

#include <bits/stdc++.h>
#define endl "\n"
#define int long long
using namespace std;

int n, a[410], b[410][410], c[410];
void solve(){
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i], c[i]=c[i-1]+a[i];
	for(int l = 1; l <= n-1; l++){
		for(int i = 1; i+l <= n; i++){
			b[i][i+l] = 1e18;
			for(int j = 1; j <= l;j++){
				b[i][i+l] = min(b[i][i+l-j]+b[i+l-j+1][i+l],b[i][i+l]);
			}
			b[i][i+l]+=c[i+l]-c[i-1];
//			cout << b[i][i+l] << ' ' << i << ' ' << i+l << endl;
		}
	}
	cout << b[1][n];
}
signed main (){
	ios::sync_with_stdio(false);
	cin.tie(nullptr); 
	int T;
//	cin >> T;
	T = 1;
	while (T--) {
		solve();
	}
	return 0;
}

相關文章