首页 > 其他分享 >最小点覆盖问题

最小点覆盖问题

时间:2024-09-19 20:35:46浏览次数:1  
标签:ok 覆盖 int 最小 问题 枚举 vector z1 dp

E. Algebra Flash
做这道题的时候新学的算法, 叫做最小点覆盖.
令 \(c_i\) 为在 \(i\) 位置的颜色
首先了解题意, 由于我们只能跨 \(1\) ~ \(2\)步, 故此时如果有 \(c_i = c_{i+1}\), 则 \(c_i\) 这个颜色是必选的, 若两者不相等, 也必须从两者里面选择出一个来, 那么我们可以给相邻的两点连上一条边, 意味着两个点必须有一个点被选择, 这样就转化成: 第 \(1\) 个点和第 \(n\) 个点必选, 其余相邻的点必选一个, 那么就可以转化成最小点覆盖问题, 我们可以把 \(m\) 个点对半分, 然后枚举出前 \(\frac{m}{2}\) 个点的状态, 然后再和剩下的点进行合并.

  • 在枚举过程中, 会出现状态某两个点没有选择, 而我们必须要在这两个点中选择一个点, 所以我们此时的情况是无解的, 直接设置成无穷大即可
  • 需要倒着枚举状态, 因为即使出现无解的情况, 我们也要对其进行更新, 也就是符合情况的最小的超集, 例如存在两个点没有选择, 而这两点必须选择一点, 那么我们首先要把这个状态设置成无穷大, 然后去枚举所有没有选择的点, 对他的超集, 也就是符合条件的进行更新, 这样做是为了在合并的时候, 只要后半段有解, 前半段即使无解, 由于我们枚举了超集, 再加上某个点使得这个状态最小, 从而合并
  • 时间复杂度\(O(2^{\frac{m}{2}} * (\frac{m}{2})^2)\)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 1e18, mod = 1e9 + 7;
signed main()
{
    std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

    int n, m; cin >> n >> m;
   
    vector<int> c(n + 1), cost(m + 1);
    for(int i = 1; i <= n; i++) cin >> c[i];
    for(int i = 1; i <= m; i++) cin >> cost[i];

    vector<vector<bool>> a(m + 1, vector<bool> (m + 1));    
    for(int i = 1; i <= n; i++){
        if(i > 1) a[c[i]][c[i - 1]] = true;
        if(i < n) a[c[i]][c[i + 1]] = true;
    }
    a[c[1]][c[1]] = a[c[n]][c[n]] = true;

    int z1 = m / 2, z2 = m - z1;
    vector<int> dp(1LL << (z1 + 1));
    for(int i = (1LL << z1) - 1; i >= 0; i--){ // O(2 ^ (m / 2) * (m / 2) * (m / 2))
        bool ok = true;
        
        for(int j = 1; j <= z1; j++){
            if((i >> (j - 1) & 1) == 0){
                for(int k = 1; k <= z1; k++){
                    if((i >> (k - 1) & 1) == 0 && a[j][k]){
                        ok = false;
                    }
                }
            }
        }

        if(ok){
            for(int j = 1; j <= z1; j++){
                if((i >> (j - 1) & 1)){
                    dp[i] += cost[j];
                }
            }
        } else{
            dp[i] = INF;
            for(int j = 1; j <= z1; j++){
                if((i >> (j - 1) & 1) == 0){
                    dp[i] = min(dp[i], dp[i ^ (1 << (j - 1))]);
                }
            }
        }

    }

    int res = INF;    
    for(int i = 0; i <= (1LL << z2) - 1; i++){
        bool ok = true;

        for(int j = 1; j <= z2; j++){
            if((i >> (j - 1) & 1) == 0){
                for(int k = 1; k <= z2; k++){
                    if((i >> (k - 1) & 1) == 0 && a[z1 + j][z1 + k]){
                        ok = false;
                    }
                }
            }
        } 

        if(!ok) continue;

        int cur = 0, should = 0;
        for(int j = 1; j <= z2; j++){
            if((i >> (j - 1) & 1)){
                cur += cost[z1 + j];
            } else{
                for(int k = 1; k <= z1; k++){
                    if(a[k][j + z1]){
                        should |= (1LL << (k - 1));                        
                    }
                }
            }
        }
        
        res = min(res, cur + dp[should]);

    }

    cout << res << '\n';

    return 0;
}

标签:ok,覆盖,int,最小,问题,枚举,vector,z1,dp
From: https://www.cnblogs.com/o-Sakurajimamai-o/p/18421269

相关文章

  • 线程三:线程安全问题及其解决方法
    一:引入代码演示线程安全问题:200000次自增多线程运算publicclassThreadDemo12{privatestaticintcount=0;publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt1=newThread(()->{for(inti=0;i<......
  • 循环链表实现约瑟夫问题
    问题描述利用循环链表实现:读入2个整数A和B,然后输出2个整数C和D。其中A表示人数,这些人的id分别为1,2,3,...A,他们按照id依次围成一圈。从id为1的人开始报数,报到B的人退出圈,然后从下一个人开始重新报数,报到B的人又退出圈,如此反复,直到剩下2人为止。C和D为剩下的......
  • 【高中数学/等比数列/基本不等式】已知正项等比数列{an}满足a_4^2=a_m*a_n,则9/m+1/n
    【问题】(甘肃高台县第一中学某年模拟测试(文))已知正项等比数列{an}满足a_4^2=a_m*a_n,则9/m+1/n的最小值为?【出处】《高考数学极致解题大招》P119典例16中原教研工作室编著【解答】a_4=aq^3a_4^2=a^2*q^6a_m=aq^m-1a_n=aq^n-1因为a_4^2=a_m*a_n,所以q^6=q^m+n-2,即m+n=89/m+1/n=9/m*......
  • IIS服务器上传文件,超过40M报错问题
    如果在applicationHost.config中没有找到maxAllowedContentLength设置,可以手动添加它。请按照以下步骤操作:1.打开applicationHost.config使用文本编辑器(如记事本)以管理员权限打开C:\Windows\System32\inetsrv\config\applicationHost.config。2.添加或修改请求限制在......
  • 修复Windows系统中mt6.dll文件缺失或损坏的问题——了解mt6.dll错误的原因及有效的解
    在使用Windows操作系统时,有时会遇到诸如“找不到mt6.dll”或“mt6.dll已损坏”等错误信息。这些问题可能会阻止应用程序的正常运行,给用户带来不便。本文将探讨这些问题的常见原因,并提供有效的解决方法,帮助用户快速恢复正常操作。原因分析文件缺失:用户可能无意中删除了mt6.......
  • 【配送路径规划】蚁群算法求解多配送中心+多车辆+时间窗的冷链物流车辆路径规划问题(目
    ......
  • 2024Mysql And Redis基础与进阶操作系列(6)作者——LJS[含MySQL 多表之一对一/多;多对多;
    MySQL多表操作1多表关系简介1.1一对一关系比如1.2一对多/多对一关系比如:实现规则:1.3多对多关系举例:规则:2.多表联合查询简介多表查询有以下分类知识补充——笛卡尔积(了解即可)交叉连接查询[产生笛卡尔积]内连接查询(使用的关键字innerjoin--inner可以省......
  • 线上间歇性卡顿问题
    事情起因最近一段时间我们公司有个项目是做视力筛查的,平时都是正常的,但是最近这两天突然会时不时地卡顿一下,一卡就是几分钟。 排查过程1.查看日志卡顿首先是排查日志,日志报的是feign调用学生服务超时,进到学生服务查看时,看到日志报的是事务超时 2.继续排查,既然是事务超时,......
  • Capital许可使用常见问题解答
    在使用Capital软件的过程中,许多用户可能会遇到关于许可使用的各种问题。为了帮助大家更好地理解和合规使用Capital软件,我们整理了一份常见问题解答,希望能为您提供有价值的参考。一、Capital许可证的类型有哪些?Capital提供多种许可证类型,包括永久许可证、订阅许可证等。永久许可......
  • 14:00面试,15:00就出来了,问的问题过于变态了。。。
    从小厂出来,没想到在另一家公司又寄了。到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到9月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%,这下搞的饭都吃不起了。还在有个朋友内推我去了一家互联网公司,兴冲冲见面试官,没想到一道......