题面

​ 这个题目大意上是这样的:给定一个长度为n的01串, 其中只有k个0, 每次操作时, 从给定的m种长度中选择一种, 选择序列上长度为这种的进行反转操作, 求至少需要多少次操作使得整个串全变为1.

​ 考虑状压dp, 枚举每一位出现情况, \(f[i]\)表示状态为\(i\)时最少需要翻转的方案数. 但是\(100pts\)的数据\(n\)有\(4e4\), 所以状压dp会达到一个令人恐怖的复杂度$ O(2 ^ {40000}) \(, 因为\)k\(较小, 考虑将问题的状压转化为与\)k\(相关. 由于需要更改整个数列, 从这个上面想到了什么优化的方法吗? 差分, 差分对于序列修改是一个比较实用的优秀方法, 我们可以设差分数组\)cha[i] = seq[i] - seq[i - 1]\(, 这样的话对序列\)[l, r]\(进行修改也就是\)cha[l] + 1, cha[r + 1] - 1\(, 这样优化后我们就将\)O(n)\(的序列修改变成了\)O(1)$的简单操作.

​ 于是, 问题转化为这样: 给定一个长度为\(n\)的01串, 其中0的数目不超过\(2k\), 每次操作时, 从给定的\(m\)种给定的距离中选择一种, 选择序列上距离为这种的两个位同时取反, 求最少需要多少次能使得整个串变为1. 观察到, 如果一个位为0, 我们一定会选择一个方式去消去这个0, 要么是一个1和他进行操作, 此时可视为交换这两个数, 要么是一个0与他进行操作, 此时可视为这两个数同时消去, 这样我们又可以转化问题了

​ 问题再次转化为这样:给定一个有n个点的图, 其中只有不超过\(2k\)的存在物品, 每次操作时, 从给定的m种距离中选择一种, 移动这个物品或与与他相距为这个距离的点同时消去, 问最少需要多少次操作使得所有的距离都消失.消去一个物品相当于将其中一个物品移动至另外一个物品的位置, 代价即为最少所需的步数, 同时, 每个点只有m条边, 我们发现这种操作可以用时间复杂度只有\(O(nmk)\)的\(BFS\)来解决.

​ 问题转化为:图上有2k个物品, 选择其中两个可以消去, 分别有不同的代价, 求使得所有物品小时的最小代价, 至此, 我们成功将问题转化为与k相关的状压dp, 多好啊.

具体代码

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define N 40005
using namespace std; int n, k, m, cr[N], lth[100], pos[100], num[N], dis[20][20], f[1 << 20], step[N], cnt; inline int read()
{
int x = 0, w = 1;
char c = getchar();
while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * w;
} inline void SPFA(int x)
{
memset(step, -1, sizeof(step));
queue <int> q;
q.push(pos[x]); step[pos[x]] = 0;
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = 1; i <= m; i++)
{
for(int j = -1; j <= 1; j += 2)
{
int end = u + lth[i] * j;
if(end <= 0 || end > n || step[end] != -1) continue;
step[end] = step[u] + 1; q.push(end);
}
}
}
for(int i = 1; i <= n; i++) if(num[i] != 0) dis[x][num[i]] = step[i];
} int main()
{
// freopen("starlit.in", "r", stdin);
// freopen("starlit.out", "w", stdout);
n = read(); k = read(); m = read();
for(int i = 1; i <= k; i++) cr[read()] = 1;
for(int i = 1; i <= m; i++) lth[i] = read();
n++;
for(int i = 1; i <= n; i++) if(cr[i] ^ cr[i - 1]) { pos[++cnt] = i; num[i] = cnt; }
//记录下差分数组中为1(其实就是上面所说的为0)的位置.
memset(dis, -1, sizeof(dis));
for(int i = 1; i <= cnt; i++) SPFA(i);//BFS其实就是SPFA变一下.
memset(f, 0x3f, sizeof(f));
f[0] = 0;
for(int u = 0; u < (1 << cnt); u++)
for(int i = 1; i <= cnt; i++)
if(!(u & (1 << (i - 1))))
for(int j = i + 1; j <= cnt; j++)
if(!(u & (1 << (j - 1))))
if(dis[i][j] != -1)
{
int v = u | (1 << (i - 1)) | (1 << (j - 1));
f[v] = min(f[v], f[u] + dis[i][j]);
}//状压dp, 各位看官应该都看得懂吧...
printf("%d\n", f[(1 << cnt) - 1]);
return 0;
}

​ 星空这道题与这道题有异曲同工之妙, 可以对比着做一下.

[luogu3943] 星空的更多相关文章

  1. 使用canvas绘制一片星空

    效果图 五角星计算方式 代码 <body style="margin:0px;padding:0px;width:100%;height:100%;overflow:hidden;&q ...

  2. WPF星空效果

    效果 前阵子看到ay的蜘蛛网效果和知乎的登录页背景,觉得效果很酷.自己也想写一个.于是写着写着就变成这样了.少女梦幻的赶脚有木有.我这有着一颗少女心的抠脚大汉 实现思路 分为两个部分: 1.星星无休止 ...

  3. 【Canvas】canva实例-星空、日出的效果

    一.描述 模仿星空后黎明到来,日出的场景 二.代码 <!DOCTYPE html> <html> <head> <title></title> ...

  4. canvas星空和图形变换

    图形变换. 一.画一片星空 先画一片canvas.width宽canvas.height高的黑色星空,再画200个随机位置,随机大小,随机旋转角度的星星. window.onload=function ...

  5. 使用JavaScript在Canvas上画出一片星空

    随着Html5的迅猛发展,画布也变得越来越重要.下面我就写一个关于在canvas上画出一片星空的简单的代码的示例. 理论基础 初始化一个canvas,获得一个用于绘制图形的上下文环境context.并 ...

  6. 爬虫 - 动态分页抓取 游民星空 的资讯 - bs4

    # coding=utf-8 # !/usr/bin/env python ''' author: dangxusheng desc : 动态分页抓取 游民星空 的资讯 date : 2018-08- ...

  7. js实现星空效果

    本次主要是来实现上面的星空效果:在黑色的背景下面,有大小不一的星星在闪烁,当鼠标悬浮时,星星放大并旋转. 首先,我们需要一个大的夜空容器和放星星的容器: <!DOCTYPE html> & ...

  8. 【BZOJ-2864】战火星空 计算几何 + 最大流

    2864: 战火星空 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 33  Solved: 14[Submit][Status][Discuss] D ...

  9. HTML5 Canvas ( 贝塞尔曲线, 一片星空加绿地 ) quadraticCurveTo, bezierCurveTo

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

随机推荐

  1. tcpcopy简介

    本文内容是整理自 王斌的博客(http://blog.csdn.net/wangbin579)和郑钧的博客(http://www.cnblogs.com/zhengyun_ustc),以便让自己可以有 ...

  2. spring 中 InitializingBean 接口使用理解

    前言:这两天在看 spring 与 quart 的集成,所以了解到 spring 是如何初始化 org.springframework.scheduling.quartz.SchedulerFacto ...

  3. WCF中DataContract和MessageContract的区别

    一.代码案例 首选建立2个WCF Service,它们分别使用不同的Contract,同时创建一个Console控制台项目,作为Client: 其中,WcfServiceWithDataContrac ...

  4. xamarin.android App在后台运行不退出

    /// <summary> /// 重写按键事件 /// </summary> /// <param name="keyCode"></p ...

  5. 记录在window平台安装python的第三库(py,whl)

    在下载python的第三库文件的时候,有些库文件有exe的发行版,但是有些第三库并没有找到针对于window的可执行文件安装包即exe文件,而只有源代码文件即py文件,和whl文件. 下面记录一下在w ...

  6. 从敲入 URL 到浏览器渲染完成、对HTTP协议的理解

    1. 大致过程 当你这样子回答的时候: 用户输入 url 地址,浏览器查询 DNS 查找对应的请求 IP 地址 建立 TCP 连接 浏览器向服务器发送 http 请求,如果服务器段返回以 301 之类 ...

  7. React Native常用组件样式总结

    在react 中,有时要使用 style 指定样式 ,如要跟随放大比例关系,展示图标. const stylebutton = {width:25*scalesize, height:25*scale ...

  8. 润乾V4报表放入WEBINF保护目录下如何实现

     润乾报表放入WEBINF保护目录下如何实现 WEB-INF下面的文件都是受保护的,客户为了保护项目的文件不受到非法的访问,jsp页面都放在WEB-INF下,那润乾报表放入WEB-INF保护目录下 ...

  9. mybatis 一对多 id标签作用

    一对多 MyBatis的resultMap只用于配置结果如何映射,id的唯一作用就是在嵌套的映射配置时判断数据是否相同,当配置id标签时,MyBatis只需要逐条比较所有数据中id标签字段值是否相同即 ...

  10. private 与 super

    public class Person { private String name; private int age; } public class Student extends Person { ...