首页 > 其他分享 >从CF1941D与1741E初探可达性DP

从CF1941D与1741E初探可达性DP

时间:2024-03-13 12:55:22浏览次数:32  
标签:opt std now int DP CF1941D 可达性 dp dis

Problem - D - Codeforces

用记忆化搜索过的,然而DP能快300ms

记忆化搜索 | \(\texttt{set}\)模拟

核心思路一致,都是通过定义一个状态,即在第t次到达第now点来去重剪枝

记忆化搜索

int n, m, x;
std::vector<std::pair<int, char>> step;
std::set<int> S;

int getClock(int x, int dis) {
    dis %= n;
    if (x + dis > n) return (x + dis) % n;
    else return x + dis;
}

int getAntiClock(int x, int dis) {
    dis %= n;
    if (x - dis < 1) return n - (dis - (x - 1)) + 1; 
    else return x - dis;
}

bool vis[1010][1010];

void dfs(int now, int t) {
    if (t == m) {S.insert(now); return ;}
    if (vis[now][t]) {return ;}
    vis[now][t] = true;
    auto[dis, opt] = step[t];
    if (opt == '?' or opt == '0') {
        dfs(getClock(now, dis), t + 1);
    }
    if (opt == '?' or opt == '1') {
        dfs(getAntiClock(now, dis), t + 1);
    }
}

\(\texttt{set}\)​模拟

这里STD还利用了几个取模trick

首先是把 \(x \mod{n}\) 转化成 \((x - 1)\mod {n} + 1\) ,防止 \(x = n\) 时想要得到 \(n\) 却得到 \(0\)。

首先是逆时针可能是负数,所以最后再加上 \(n\) 防止取模失效。

//本质上也是记忆化搜索
//通过set自动把当前位置且次数都相同的状态去重了

void solve() {
    int n, m, x;
    std::cin >> n >> m >> x;
    std::set<int> S[2];
    bool cur(false);
    S[cur].insert(x);
    while (m--) {
        int d; char opt;
        std::cin >> d >> opt;
        while (!S[cur].empty()) {
            int now(*S[cur].begin());
            S[cur].erase(now);
            if (opt == '?' or opt == '0') {
                S[cur ^ 1].insert((now + d - 1) % n + 1);
            }
            if (opt == '?' or opt == '1') {
                S[cur ^ 1].insert((now - d + n - 1) % n + 1);
            }
        }
        cur ^= 1;
    }
    std::cout << sz(S[cur]) << '\n';
    for (auto& x : S[cur]) std::cout << x << ' ';
    std::cout << '\n';
}

可达性DP

即定义状态 \(dp_{i, j}\) 为第 \(i\) 次操作第 \(j\) 点的可达性。

转移方程很直接

\[dp_{i, j} = dp_{i - 1, (j + d - 1)\mod n + 1}(opt = \text{?} \| opt = \text{0}) \]

\[dp_{i, j} = dp_{i - 1, (j - d + n - 1)\mod n + 1}(opt = \text{?} \| opt = \text{1}) \]

原始写法

因为该题没有卡空间,所以能过

void solve() {
    int n, m, x;
    std::cin >> n >> m >> x;
    std::vector dp(m + 1, std::vector<short>(n + 1));
    dp[0][x] = 1;
    for (int i = 1; i <= m; i++) {
        int d; char opt;
        std::cin >> d >> opt;
        if (opt == '?' or opt == '0') {
            for (int j = 1; j <= n; j++) {
                dp[i][j] |= dp[i - 1][(j - d + n - 1) % n + 1];
            }
        }
        if (opt == '?' or opt == '1') {
            for (int j = 1; j <= n; j++) {
                dp[i][j] |= dp[i - 1][(j + d - 1) % n + 1];
            }
        }
    }
    std::cout << std::count(all(dp[m]), 1) << '\n';
    for (int i = 0; i <= n; i++) if (dp[m][i] == 1) {
        std::cout << i << ' ';
    }
    std::cout << '\n';
}

优化空间

t宝和jls都是进一步优化了空间,因为该状态只会从上一步转移而来,所以完全可以省去第一维

void solve() {
    int n, m, x;
    std::cin >> n >> m >> x;
    x--;
    std::vector<bool> dp(n);
    dp[x] = true;
    for (int i = 0; i < m; i++) {
        int d; char opt;
        std::cin >> d >> opt;
        std::vector<bool> newDp(n);
        for (int j = 0; j < n; j++) if(dp[j]) {//从0开始,直接避免了取模会为0的问题
            if (opt != '1') {
                newDp[(j + d) % n] = true;
            }
            if (opt != '0') {
                newDp[(j - d + n) % n] = true;
            }
        }
        dp = newDp;
    }
    std::cout << std::count(all(dp), 1) << '\n';
    for (int i = 0; i < n; i++) if (dp[i]) {
        std::cout << i + 1 << ' ';
    }
    std::cout << '\n';
}

另一道题

Problem - E - Codeforces

依然可以用可达性DP。

定义 \(dp_i\) 为 \([1, i]\) 区间是否合法

假设 \(a_i\)​ 就是表示区间长度的值,则通过之前合法的情况递推

这里取 \(i - 1\) 是因为 \(i\) 时表示长度的那个数的下标,不用算进去

如果他在他表示区间的左边,则 \([1, i + a_i]\) 的合法条件是 \([1, i - 1]\) 合法

如果他在他表示区间的右边,则 \([1, i]\) 的合法条件是 \([1, i - 1 - a_i]\) 合法

void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) std::cin >> a[i];
    std::vector<bool> dp(n + 1);
    dp[0] = true;
    for (int i = 1; i <= n; i++) {
        if (i + a[i] <= n and dp[i - 1]) {
            dp[i + a[i]] = true;
        }
        if (i - 1 - a[i] >= 0 and dp[i - 1 - a[i]]) {
            dp[i] = true;
        }
    }
    dp[n] ? YES : NO;
}

标签:opt,std,now,int,DP,CF1941D,可达性,dp,dis
From: https://www.cnblogs.com/kdlyh/p/18070378

相关文章

  • 【Paper Reading】7.DiT(VAE+ViT+DDPM) Sora的base论文
    VAEDDPM 分类内容论文题目ScalableDiffusionModelswithTransformers作者WilliamPeebles(UCBerkeley),SainingXie(NewYorkUniversity)发表年份2023摘要介绍了一类新的扩散模型,这些模型利用Transformer架构,专注于图像生成的潜在扩散模型。这些......
  • GDPU JavaWeb JSP基础
    正式走进Javaweb大门,了解jsp及Java在前端的体现。JSP JSP,JavaServerPages是一种基于Java技术的服务器端动态网页技术,允许开发人员在HTML页面中嵌入Java代码。通过JSP,开发人员可以创建包含静态模板和动态内容的网页。当客户端请求一个包含JSP的网页时,服务器会执行其中的J......
  • GDPU unity游戏开发 滚动小球
      解锁你的游戏大门,适合小白入门看的,通过简单的实例大概了解unity的一些基本操作。常用快捷键 CtrlC/V/X/Z对应复制/粘贴/剪切/回退很多小白都惟手熟尔了,W物体对象的位置/平移/移动 ,E物体对象旋转,R物体对象缩放,Q/Alt中键用于场景的移动,右键/Alt左键用于场景的旋转,滚......
  • 高dpi下,Vb.net调整控件位置的小经验
     高dpi下,Vb.net调整控件位置的小经验 boy8199/3vdo/club最近写了一个捕快TXT网文采集软件,结果发现在DPI不同的情况下,软件布局会变形.找了半天原因才发现是DPI的问题,默认系统的dpi是96(100%)现在显示器的屏幕比较大,所以好多人会把显示放大到125%或150%导致程序控件变形......
  • 【蓝桥杯】(台阶方案dp)
    #include<iostream>usingnamespacestd;#defineLLlonglongconstintN=1e6+5;constLLp=1e9+7;LLdp[N];inta[3];//intmain(){LLn;cin>>n;cin>>a[0]>>a[1]>>a[2];dp[0]=1;//当目标值为0时,只有一种方案for(......
  • 区间 DP
    P3146[USACO16OPEN]248G给定一个序列,每次可以将两个相邻且相同的数合并成一个数,合并结果为原数加一。求最后能得到的最大数字。\(n\le248\),\(1\lea_i\le40\)。最暴力的,设状态\(f_{l,r,k}\)表示区间\([l,r]\)能否最终合并为数字\(k\)。也就是说\(f_{l......
  • 三、jsPlumb实现流程图配置--Endpoint详细参数
    一、前言基于上一篇文章中已经搭建好的jsPlumb项目,在此篇文章中演示Endpoint的一些参数以及参数的效果。二、Endpoint创建在一个节点上创建Endpoint有三种方式://方式一:直接使用字符串指定类型。注意:大小写敏感//圆点形constendpoint1=jsPlumb.value.addEndpoint......
  • Logstash接收udp/tcp数据 python+ udp/tcp +logstash +elasticsearch
    Logstash接收udp/tcp数据背景:在 Logstash数据源为日志文件操作 基础上进行一、配置文件1.D:\usr\local\etc\logstash\pipeline1目录下logstash.conf文件配置input{stdin{}udp{host=>"0.0.0.0"#从5000端口获取日志port=>5000......
  • 【动态规划】线性dp /训练记录/
    开篇碎碎念前些日子写期望dp,但是...cf的那个C可以dp但是没有开出来,于是决定重新开始练dp√(一定是因为题目做的不够多捏,加训!)是根据这个题单来练哒,指路:【动态规划】普及~省选的dp题然后边练边整理一下思路什么的)))基本思路其实动态规划的本质就是暴力(这也是可以说的吗(遁),考虑好......
  • WordPress:常见问题及解决方案
    解决头像不显示问题默认头像效果:Gavatar的头像在国内不能正常访问,如图:设置:把以下php代码添加到模板函数funtions.php文件中if(!function_exists('get_cravatar_url')){/***把Gravatar头像服务替换为Cravatar*@paramstring$url*@return......