AtCoder Beginner Contest 044

胖柚の工作室發表於2024-08-15

A - Tak and Hotels (ABC Edit)

#include <bits/stdc++.h>

using namespace std;
using i64 = long long;

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int n, k, x, y;
	cin >> n >> k >> x >> y;
	
	int ans = 0;
	if (n <= k) {
		ans += n * x;
	} else {
		ans += k * x + (n - k) * y;
	}
	cout << ans;
	return 0;
}

B - Beautiful Strings

#include <bits/stdc++.h>

using namespace std;
using i64 = long long;

int st[26];

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	string s;
	cin >> s;
	for (auto i : s) {
		st[i - 'a'] ++;
	}
	for (int i = 0; i < 26; i++) {
		if (st[i] % 2 == 1) {
			cout << "No\n";
			return 0;
		}
	}
	cout << "Yes";
	return 0;
}

C - Tak and Cards

\(\rm f[i][j][k]\) 表示前 \(i\) 個物品中,選擇 \(j\) 個物品,價值之和為 \(k\) 的方案數。狀態轉移方程為:\(dp[i][j][k]=dp[i-1][j][k]+dp[i-1][j-1][k-x[i]]\)確保不要訪問到負數下標,下標從1開始

#include <bits/stdc++.h>

using namespace std;
using i64 = long long;

long long f[51][51][2600], pre[1005];

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int N, A;
	cin >> N >> A;
	vector<int> x(N + 1);
	for (int i = 1; i <= N; i++) {
		cin >> x[i];
		pre[i] = pre[i - 1] + x[i];
	}
	
	for (int i = 0; i <= N; i++) f[i][0][0] = 1;//初始化,啥都不選也是一種方案
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= i; j++) {
			for (int k = 1; k <= pre[i]; k++) {
				if (k >= x[i]) f[i][j][k] += f[i - 1][j - 1][k - x[i]];
				f[i][j][k] += f[i - 1][j][k];
			}
		}
	}
	
	long long ans = 0;
	for (int i = 1; i <= N; i++) ans += f[N][i][A * i];
	cout << ans;
	return 0;
}

其實這就是變形後的 \(01\) 揹包問題,可以將第一維最佳化掉,但需注意改變迴圈的遍歷順序,從小到大的狀態更新方式,若仍然順序遍歷的話,被忽略的 \(i-1\) 維度的 \(j\)\(k\) 會被汙染,影響狀態轉移。因此需要逆向列舉

#include <bits/stdc++.h>

using namespace std;
using i64 = long long;

long long f[51][2600], pre[1005];

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int N, A;
	cin >> N >> A;
	vector<int> x(N + 1);
	for (int i = 1; i <= N; i++) {
		cin >> x[i];
		pre[i] = pre[i - 1] + x[i];
	}
	
	f[0][0] = 1;
	for (int i = 1; i <= N; i++) {
		for (int j = i; j >= 1; j--) {
			for (int k = pre[i]; k >= x[i]; k--) {
				f[j][k] += f[j - 1][k - x[i]];
			}
		}
	}

	long long ans = 0;
	for (int i = 1; i <= N; i++) ans += f[i][A * i];
	cout << ans;
	return 0;
}