abc082d <bitset 状压dp>

发布时间 2023-07-15 09:08:00作者: O2iginal

题目

D - FT Robot

思路

  • 动态规划的方式记录每次行动后, 机器人在坐标系中所有可能位置
  • 通过bitset对状态进行压缩, 即每个位置有机器人true or 没有 false
  • 因为机器人仅按坐标轴方向前进, 因而可将 x y 坐标状态分开存储, 进一步降低计算量, 也方便使用 bitset
  • 通过bitset的移位运算, 进行状态更新

总结

  • 什么时候使用bitset 状压dp ?
    • 动态规划问题, 且每个状态仅有 true or false
    • 状态转移方程可写成状态"平移"的形式

代码

Code
// https://atcoder.jp/contests/abc082/tasks/arc087_b
// bitset 状压dp
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <bitset>
using namespace std;
using LL = long long;
const int N = 8000 * 2 + 10;
bitset<N> fx, fy;

void solv()
{
    string s;
    int x, y;
    cin >> s >> x >> y;
    s += 'T';  // 结尾补T, 用于使得最后一组F能够执行
    int n = s.size();
    fx[n] = 1, fy[n] = 1;  // 偏移, 使得原坐标系的原点位于 (n,n), 保证负数可表示
    int cntF = 0, cntT = 0;  // 移动次数, 转向次数
    for (auto ch: s)
    {
        if (ch == 'F')
        {
            cntF ++;
            // // 注意, 不能直接写成每个'F'都转移1个单位的形式, 因为仅T指令后第一个F可以选择两个方向
            // // 而其后的F仅能按照既定方向前进, 因而如果每遇到一个F都使用以下转移方程, 会出现错误(比正确执行到达的位置更多)
            // // 如果想要写成这种形式, 则需更改状态转移方程
            // cntF = 1;
            // if (!cntT) fx = fx << cntF;
            // else if (cntT & 1) fy = (fy << cntF) | (fy >> cntF);
            // else fx = (fx << cntF) | (fx >> cntF);
        }
        else
        {
            if (!cntT) fx = fx << cntF;  // 首次前进, 向东, x轴正方向
            else if (cntT & 1) fy = (fy << cntF) | (fy >> cntF);  // 累计旋转次数为奇数, 则相南或北
            else fx = (fx << cntF) | (fx >> cntF);  // 旋转次数为偶数
            cntT ++;  // 进行本轮旋转
            cntF = 0;
        }
    }
    cout << (fx[n+x]&&fy[n+y] ? "Yes" : "No") << endl;

}

void solv0()
{
    string s;
    int x, y;
    cin >> s >> x >> y;
    int n = s.size();
    fx[n] = 1, fy[n] = 1;
    int cntF = 0, cntT = 0;
    for (auto ch: s)
    {
        if (ch == 'F')
        {
            if (cntT == 0) fx = fx << 1;
            else if (cntT & 1) fy = (fy << 1) | (fy >> 1);
            else fx = (fx << 1) | (fx >> 1);
        }
        else
        {
            cntT ++;
        }
    }
    cout << (fx[n+x]&&fy[n+y] ? "Yes" : "No") << endl;

}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int T = 1;
	// cin >> T;
    while (T --)
    {
        solv();
    }
    return 0;
}