题目链接
贪心模拟了半天,最后放弃了
题意
给你一串从$1-n$的序列,其中部分未知(表示为0),补全序列使得相邻数值奇偶性相反的数量最少
相邻数值的奇偶性相反:两个相邻的两个数值,其中一个为奇数另外一个为偶数
分析
一开始用了贪心,结果卡在第十二个样例,然后改成dp
定义dp数组如下
得到状态转移方程
| 12
 
 | dp[i][j][1] = min(dp[i - 1][j - 1][0] + 1, dp[i - 1][j - 1][1]);dp[i][j][0] = min(dp[i - 1][j][1] + 1, dp[i - 1][j][0]);
 
 | 
当然这得看这个位置本身是不是已经有了数值,如果为0则两个都需要,如果已经有数值了就按照原来的数值进行dp
AC代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 
 | #include <bits/stdc++.h>
 using namespace std;
 
 void solve() {
 int n;
 int dp[120][60][2], value[120];
 cin >> n;
 for (int i = 0; i < n; ++i) {
 cin >> value[i];
 }
 memset(dp, 0x3f, sizeof(dp));
 if (value[0] == 0)
 dp[0][1][1] = dp[0][0][0] = 0;
 else
 dp[0][value[0] & 1][value[0] & 1] = 0;
 for (int i = 1; i < n; ++i) {
 for (int j = 0; j <= min(i + 1, (n + 1) / 2); ++j) {
 if ((value[i] & 1 || value[i] == 0) && j > 0)
 dp[i][j][1] = min(dp[i - 1][j - 1][0] + 1, dp[i - 1][j - 1][1]);
 if (!(value[i] & 1))
 dp[i][j][0] = min(dp[i - 1][j][1] + 1, dp[i - 1][j][0]);
 }
 }
 cout << min(dp[n - 1][(n + 1) / 2][1], dp[n - 1][(n + 1) / 2][0]) << endl;
 }
 
 int main() {
 ios_base::sync_with_stdio(false);
 cin.tie(nullptr);
 cout.tie(nullptr);
 #ifdef ACM_LOCAL
 freopen("in.txt", "r", stdin);
 freopen("out.txt", "w", stdout);
 long long test_index_for_debug = 1;
 char acm_local_for_debug;
 while (cin >> acm_local_for_debug) {
 cin.putback(acm_local_for_debug);
 if (test_index_for_debug > 20) {
 throw runtime_error("Check the stdin!!!");
 }
 auto start_clock_for_debug = clock();
 solve();
 auto end_clock_for_debug = clock();
 cout << "Test " << test_index_for_debug << " successful" << endl;
 cerr << "Test " << test_index_for_debug++ << " Run Time: "
 << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
 cout << "--------------------------------------------------" << endl;
 }
 #else
 solve();
 #endif
 return 0;
 }
 
 |