AtCoder Beginner Contest 044

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;
}
posted @ 2024-08-15 21:44  胖柚の工作室  阅读(15)  评论(0)    收藏  举报