[luogu3943] 星空
题面
这个题目大意上是这样的:给定一个长度为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] 星空的更多相关文章
- 使用canvas绘制一片星空
效果图 五角星计算方式 代码 <body style="margin:0px;padding:0px;width:100%;height:100%;overflow:hidden;&q ...
- WPF星空效果
效果 前阵子看到ay的蜘蛛网效果和知乎的登录页背景,觉得效果很酷.自己也想写一个.于是写着写着就变成这样了.少女梦幻的赶脚有木有.我这有着一颗少女心的抠脚大汉 实现思路 分为两个部分: 1.星星无休止 ...
- 【Canvas】canva实例-星空、日出的效果
一.描述 模仿星空后黎明到来,日出的场景 二.代码 <!DOCTYPE html> <html> <head> <title></title> ...
- canvas星空和图形变换
图形变换. 一.画一片星空 先画一片canvas.width宽canvas.height高的黑色星空,再画200个随机位置,随机大小,随机旋转角度的星星. window.onload=function ...
- 使用JavaScript在Canvas上画出一片星空
随着Html5的迅猛发展,画布也变得越来越重要.下面我就写一个关于在canvas上画出一片星空的简单的代码的示例. 理论基础 初始化一个canvas,获得一个用于绘制图形的上下文环境context.并 ...
- 爬虫 - 动态分页抓取 游民星空 的资讯 - bs4
# coding=utf-8 # !/usr/bin/env python ''' author: dangxusheng desc : 动态分页抓取 游民星空 的资讯 date : 2018-08- ...
- js实现星空效果
本次主要是来实现上面的星空效果:在黑色的背景下面,有大小不一的星星在闪烁,当鼠标悬浮时,星星放大并旋转. 首先,我们需要一个大的夜空容器和放星星的容器: <!DOCTYPE html> & ...
- 【BZOJ-2864】战火星空 计算几何 + 最大流
2864: 战火星空 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 33 Solved: 14[Submit][Status][Discuss] D ...
- HTML5 Canvas ( 贝塞尔曲线, 一片星空加绿地 ) quadraticCurveTo, bezierCurveTo
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
随机推荐
- 使用springcloud gateway搭建网关(分流,限流,熔断)
Spring Cloud Gateway Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 ...
- HTML列表(组标签)+div(布局标签)与span
一.列表 HTML中常见的列表有三种,分别是: 1.无序列表,是一组描述列表语义的组标签,列表中每个项之间没有先后顺序:如图: 1)组标签:组标签就是由多个标签组成的一个整体,它们之间共同存在:例如 ...
- 不要在对抽象类接口abstract virtual什么的混淆不清了
(最近带一个新手入门 讲这边老费力了.) 接口和抽象类不过都是类的抽象罢了,这是他们的本质,只不过人们的思维角度不同而已,一个偏向为行为契约上的抽象(接口) 一个更像大自然中的繁衍关系(抽象类). 直 ...
- 在AE二次开发中出“正试图在 OS 加载程序锁内执行托管代码。不要尝试在 DllMain 或映像初始化函数内运行托管代码,这样做会导致应用程序挂起。”异常解决方案
今天的一个项目总用到了AE的开发组件,也就是ESRI公司提供的一系列的开发包(组件)都是以dll(动态链接库的形式)然后今天在调试的时候却出现了“正试图在 OS 加载程序锁内执行托管代码.不要尝试在 ...
- 基于jQuery的软键盘
基于jQuery的软键盘 前些天写了一个基于基于jQuery的数字键盘,今天给大家带来一个基于jQuery的全字母键盘插件(支持全字母大小写切换,数字输入,退格清除,关闭功能,可调整大小和键盘位置 ...
- JS 时间转化为几分钟前 几小时前 几天前
背景:最近公司要做动态列表,类似于微信朋友圈.动态创建时间就需要显示为 刚刚.几分钟前.几小时前.几天前.2018-05-15,这样的形式. 代码如下 var minute = 1000 * 60; ...
- textarea显示默认值
点击不显示默认值,鼠标离开如果没有内容就显示默认值,如果有内容就显示内容. <textarea class="area" onfocus="if(value=='请 ...
- 探索ORM之iBati(一)
ibatis iBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目.最初侧重于密码软件的开发,现在是一个基于Jav ...
- 【涨姿势】Prince2和PMP的区别,大多数人都没搞清楚!
项目管理领域有2个流行的知识体系: ☑ 一个是美国项目管理协会(PMI)开发的“项目管理知识体系(PMBOK,Project Management Body of Knowledge)”,目 ...
- SQL Server ->> 数据类型不一致比较时的隐式转换
当使用操作符进行比较的时候,两边数据类型不一致的情况下,数据类型优先级别低的会往优先级别高的发生隐式转换.下面的参考链接是优先级别列表. 参考: Data Type Precedence (Trans ...