由题意可知相邻两个翻转代价x,不相邻两个翻转代价为y,首先考虑不可能将a变成b的情况,奇数个位置不同一定不能完成,其次考虑y如果不大于x的话,当不同的个数=2且这两个不同的位置紧邻,看到n>=5,所以一定可以用两个y替代一个x代价,所以比较2*y和x的大小,其余因为y的代价更小,一定能全用y代价把所有的都翻转,最后考虑y大于x的情况
DP,最大代价一定是全用y,考虑如果其中某几对位置相邻的用x的话比纯用y少了多少代价,设dp[i]为截止i和i+1,用y比用x的代价最多多了多少,所以cost记录的是i和i+1之间用y比用x代价多了多少,因为pos的下标是0base,所以当i==0的时候,要么用cost要么用y,因为这里算的是用y比用x多了多少代价,所以cost和0取max,当i==1的时候要么i和i+1取更优的cost,要么什么都不做,dp[i]=dp[i-1],说明截止i-1和i代价更优,当i>1,这时考虑什么都不做dp[i]=dp[i-1],或者dp[i-2]+cost,即截止i-2和i-1的代价+i和i+1的代价,最后只需要用最多的价值-所有用x时多余的代价
AC代码:
#include <bits/stdc++.h> using namespace std; using LL = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { int n; LL x, y; cin >> n >> x >> y; string s1, s2; cin >> s1 >> s2; vector<LL> pos; for (int i = 0; i < n; i++) { if (s1[i] != s2[i]) { pos.push_back(i); } } LL len = pos.size(); if (len % 2 == 1) { cout << "-1\n"; } else if (y <= x) { if (len == 2 and pos[0] + 1 == pos[1]) { cout << min(x, 2 * y) << '\n'; } else { cout << y * len / 2 << '\n'; } } else { vector<LL> dp(len + 1); for (int i = 0; i < len - 1; i++) { LL cost = y - x * (pos[i + 1] - pos[i]); if (i == 0) { dp[i] = max(0LL, cost); } else if (i == 1) { dp[i] = max(dp[i - 1], cost); } else { dp[i] = max(dp[i - 1], dp[i - 2] + cost); } } cout << y * len / 2 - dp[len - 2] << '\n'; } } return 0; }
由题知,直接判断第t秒(x,y)有没有球很难,根据数据范围一定要找到某个规律,发现可以考虑第i秒(x,y)经过了多少次球,要判断第t秒(x,y)有没有球就转化成第t秒(x,y)经过球的数量和第t-1秒(x,y)经过球的数量是否相等,因为箭头一开始都是先走右,再走下,所以转移的时候右侧的应为此时经过(i,j)小球数量的一半的上取整,走下侧的是此时经过(i,j)小球数量的一半的下取整,注意要判断t秒内能否有球到达(x,y),因为判断的时候是从0秒到t-x-y+1秒之间的小球才可能到达(x,y),后面的小球虽然也有,但一定都无法到达(x,y)
AC代码:
#include <bits/stdc++.h> using namespace std; using LL = long long; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; while (T--) { LL t, x, y; cin >> t >> x >> y; function<bool(LL)> f = [&](LL p) { vector<vector<LL>> dp(125, vector<LL> (125)); dp[0][0] = max(0LL, p - x - y + 1); for (int i = 0; i <= 120; i++) { for (int j = 0; j <= 120; j++) { dp[i][j + 1] += (dp[i][j] + 1) / 2; dp[i + 1][j] += dp[i][j] / 2; } } return (dp[x][y] & 1); }; if (f(t) != f(t - 1)) { cout << "YES\n"; } else { cout << "NO\n"; } } return 0; }
Codeforces Round #821 (Div. 2) D2、E
于 2023-01-03 17:04:11 首次发布