洛谷 P6366 [传智杯 #2 初赛] 特殊的翻转

分析

发现如果十六进制转二进制时以十进制作为桥,由于十六进制位数很大,转成十进制可能会炸,所以我们可以将十六进制每位分别转成二进制。

接下来考虑 dp,设状态 [ x , 0 / 1 , 0 / 1 , c ] [x,0/1,0/1,c] [x,0/1,0/1,c],表示第 x x x 位反不反转操作后第 x x x 位为 0 / 1 0/1 0/1 且操作次数为 c c c,最优化属性为 c c c,将状态按非 c c c 属性分组,状态转移分类讨论即可,最后答案取 min ⁡ ( [ n , 1 , 0 ] , [ n , 0 , 0 ] ) \min([n,1,0],[n,0,0]) min([n,1,0],[n,0,0]) 即可。

代码

#include <bits/stdc++.h>

using namespace std;
using LL = long long;

const int kMaxN = 4e6 + 5;

string s, ans;
map<char, string> mp;
int n, f[kMaxN][2][2];

void init() {
  mp['0'] = "0000";
  mp['1'] = "0001", mp['2'] = "0010", mp['3'] = "0011";
  mp['4'] = "0100", mp['5'] = "0101", mp['6'] = "0110";
  mp['7'] = "0111", mp['8'] = "1000", mp['9'] = "1001";
  mp['A'] = "1010", mp['B'] = "1011", mp['C'] = "1100";
  mp['D'] = "1101", mp['E'] = "1110", mp['F'] = "1111";
}

int main() {
  cin >> s, init();
  for (int i = 0, fl = 0; i < s.size(); i++) {
    for (int j = 0; j < 4; j++) {
      fl |= (mp[s[i]][j] == '1');
      if (fl) {
        ans.push_back(mp[s[i]][j]);
      }
    }
  }
  n = ans.size(), ans = ' ' + ans;
  memset(f, 0x3f, sizeof f);
  f[1][0][1] = 0, f[1][1][0] = 1;
  for (int i = 2; i <= n; i++) {
    if (ans[i] == '0') {
      f[i][0][0] = f[i - 1][0][0], f[i][0][1] = f[i - 1][1][0];
      f[i][1][0] = f[i - 1][1][1] + 1, f[i][1][1] = f[i - 1][0][1] + 1;
    } else {
      f[i][0][0] = f[i - 1][1][0], f[i][0][1] = f[i - 1][0][0];
      f[i][1][0] = f[i - 1][0][1] + 1, f[i][1][1] = f[i - 1][1][1] + 1;
    }
  }
  int t = min(f[n][1][0], f[n][0][0]);
  t <= n ? cout << t : cout << "No";
  return 0;
}
  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值