Codeforces 题目传送门 & 洛谷题目传送门

一个远古场的 *2800,在现在看来大概 *2600 左右罢(

不过我写这篇题解的原因大概是因为这题教会了我一个套路罢(

首先注意到每次翻转的是一个区间,那么我们可以考虑它的差分序列(这就是这题教会我的套路,碰到区间操作有关的问题不妨考虑它的差分序列,这样可将影响多个元素的区间操作转化为 \(2\) 个单点操作,其实第一次碰见这个套路是在这个题,可是由于当时比较 naive 没能及时补题并整理这些方法),那么每次操作显然是将差分序列上两个单点进行翻转,而翻转的两个单点的距离恰好等于操作区间的长度,于是现在问题转化为:你有一个初始为 \(0\) 的长度为 \(n+1\) 的序列 \(a\),你可以选择两个单点并将它们的状态翻转,满足这两个单点的距离属于某个集合 \(S\),要求最少多少次操作将序列变为给定序列 \(a'\)。

考虑怎样解决转化后的问题,首先取两个单点并翻转显然是不影响 \(1\) 的个数的奇偶性的,因此如果 \(1\) 的个数是奇数那直接 \(-1\) 即可,否则显然我们会将这些 \(1\) 两两配对,对于同一对中的两个位置 \(x,y\),我们会以如下方式让 \(x,y\) 上的数都变为 \(0\):

重复以下步骤若干次:

  • 选择一个长度 \(l\in S\) 并将 \(x\) 与 \(x+l\) 或 \(x-l\) 同时翻转,这样即可将 \(x\) 上的 \(1\) 转移到 \(x+l\) 或 \(x-l\) 上。

直到 \(x+l=y\lor x-l=y\)

我们记 \(d_{x,y}\) 为将 \(x,y\) 上的数变为 \(0\) 的最小步骤,那么显然我们可以以每个 \(1\) 为起点进行一遍 BFS 求出所有 \(d_{x,y}\)。注意到此题 \(k\le 10\),因此差分序列上 \(1\) 的个数 \(\le 20\),故考虑状压 \(dp\),\(dp_S\) 表示将 \(S\) 中的 \(1\) 变为 \(0\) 的最小代价,转移就枚举两个 \(x,y\notin S\) 然后 \(dp_{S\cup\{x\}\cup\{y\}}\leftarrow dp_S+d_{x,y}\) 即可。

据说有更优秀的二分图最小权完美匹配的做法?i 了 i 了,可惜我懒癌爆发懒得写了

复杂度 \(2^kk^2+nmk\),其中 \(k=20\)。

const int MAXN=1e4;
const int MAXM=100;
const int MAXK=20;
const int MAXP=1<<20;
const int INF=0x3f3f3f3f;
int n,k,m,a[MAXN+5],b[MAXN+5],l[MAXM+5],id[MAXN+5],pos[MAXK+5];
int dis[MAXN+5],d[MAXK+5][MAXK+5],cnt;
void bfs(int s){
queue<int> q;memset(dis,-1,sizeof(dis));
dis[s]=d[id[s]][id[s]]=0;q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
if(id[x]) d[id[s]][id[x]]=dis[x];
for(int i=1;i<=m;i++){
if(x+l[i]<=n+1){
if(!~dis[x+l[i]]) dis[x+l[i]]=dis[x]+1,q.push(x+l[i]);
} if(x-l[i]>=1){
if(!~dis[x-l[i]]) dis[x-l[i]]=dis[x]+1,q.push(x-l[i]);
}
}
}
}
int dp[MAXP+5];
int main(){
scanf("%d%d%d",&n,&k,&m);
for(int i=1,x;i<=k;i++) scanf("%d",&x),a[x]=1;
for(int i=1;i<=m;i++) scanf("%d",&l[i]);
for(int i=1;i<=n+1;i++) b[i]=a[i]^a[i-1];
for(int i=1;i<=n+1;i++) if(b[i]) id[i]=++cnt,pos[cnt]=i;
memset(d,63,sizeof(d));
for(int i=1;i<=n+1;i++) if(id[i]) bfs(i);
memset(dp,63,sizeof(dp));dp[0]=0;
// printf("%d\n",cnt);
// for(int i=1;i<=cnt;i++) for(int j=1;j<=cnt;j++)
// printf("%d%c",d[i][j]," \n"[j==cnt]);
for(int i=0;i<(1<<cnt);i++){
if(dp[i]>=INF) continue;
for(int j=1;j<=cnt;j++) for(int l=1;l<j;l++)
if((~i>>j-1&1)&&(~i>>l-1&1))
chkmin(dp[i|(1<<j-1)|(1<<l-1)],dp[i]+d[j][l]);
} printf("%d\n",(dp[(1<<cnt)-1]>=INF)?-1:dp[(1<<cnt)-1]);
return 0;
}

Codeforces 79D - Password(状压 dp+差分转化)的更多相关文章

  1. codeforces#1215E. Marbles(状压DP)

    题目大意:给出一个由N个整数组成的序列,通过每次交换相邻的两个数,使这个序列的每个相同的数都相邻.求最小的交换次数. 比如给出序列:1 2 3 2 1 ,那么最终序列应该是 1 1 2 2 3 ,最小 ...

  2. codeforces 11D(状压dp)

    传送门:https://codeforces.com/problemset/problem/11/D 题意: 求n个点m条边的图里面环的个数 题解: 点的范围只有19,很容易想到是状压. dp[sta ...

  3. 4.26 省选模拟赛 T3 状压dp 差分求答案

    LINK:T3 比较好的题目 考试的时候被毒瘤的T2给搞的心态爆炸 这道题连正解的思路都没有想到. 一看到题求删除点的最少个 可以使得不连通. 瞬间想到最小割 发现对于10分直接跑最小割即可. 不过想 ...

  4. 【模拟8.11】星空(差分转化,状压DP,最短路)

    一道很好的题,综合很多知识点. 首先复习差分:      将原来的每个点a[i]转化为b[i]=a[i]^a[i+1],(如果是求和形式就是b[i]=a[i+1]-a[i]) 我们发现这样的方便在于我 ...

  5. codeforces Diagrams & Tableaux1 (状压DP)

    http://codeforces.com/gym/100405 D题 题在pdf里 codeforces.com/gym/100405/attachments/download/2331/20132 ...

  6. Codeforces Gym 100015F Fighting for Triangles 状压DP

    Fighting for Triangles 题目连接: http://codeforces.com/gym/100015/attachments Description Andy and Ralph ...

  7. Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP

    Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...

  8. Codeforces 544E Remembering Strings 状压dp

    题目链接 题意: 给定n个长度均为m的字符串 以下n行给出字符串 以下n*m的矩阵表示把相应的字母改动成其它字母的花费. 问: 对于一个字符串,若它是easy to remembering 当 它存在 ...

  9. 状压dp Codeforces Beta Round #8 C

    http://codeforces.com/contest/8/problem/C 题目大意:给你一个坐标系,给你一个人的目前的坐标(该坐标也是垃圾桶的坐标),再给你n个垃圾的坐标,这个人要捡完所有的 ...

随机推荐

  1. 【Java虚拟机10】ClassLoader.getSystemClassLoader()流程简析

    前言 学习类加载必然离开不了sun.misc.Launcher这个类和Class.forName()这个方法. 分析ClassLoader.getSystemClassLoader()这个流程可以明白 ...

  2. .NET CLI简单教程和项目结构

    WHAT IS .NET CLI ? .NET 命令行接口 (CLI) 工具是用于开发.生成.运行和发布 .NET 应用程序的跨平台工具链. 来源:.NET CLI | Microsoft Docs ...

  3. java调用js脚本语言

    在我们开发的过程中,可能有这么一种情况,在java中需要取调用js方法完成一些事情.那么什么时候可能出现这种情况呢.比如我们使用爬虫模拟登录别的网站,但有些网站前台使用js对密码进行了加密处理,那么就 ...

  4. Noip模拟66 2021.10.2

    T1 接力比赛 思路就是直接做背包$dp$,然后看看容量相同的相加的最大值. 考虑如何在$dp$过程中进行优化 注意到转移方程的第二维枚举容量没有必要从容量总和开始枚举 那么我们便转移边统计前缀和,从 ...

  5. 五分钟搞懂spring-cloud-square

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 初识spring-cloud-square 2021年 ...

  6. 21.6.29 test

    \(NOI\) 模拟赛 \(T1\) 正解是个题解难以理解的数论,结果是组合数相加.暴力分拿满了,尝试打了 \(20*20\) 的表,最后大概打出了个三角形的表,并且帮我找到了一些性质.\(45\)p ...

  7. DDD领域驱动设计-项目包结构说明-Ⅳ

     基于DDD领域驱动设计的思想,在开发具体系统时,需要先建立不同的层级包.主要是梳理不同层面(应用层,领域层,基础设施层,展示层)包括的功能目录,每一个层面应该包括哪些模块.本例所讲述的分层是DDD落 ...

  8. X264编码测试验证

    之前在做一个rtsp直播需求,其中一个方案是要用的x264来对摄像头数据进行实时编码推流,摄像头帧率是25fps,为了验证方案的可行性,先对x264的编码速度进行一个测试研究,再确认是否要采用此方案. ...

  9. Python NameError: name 'unicode' is not defined

    Python2 的unicode 函数在 Python3 中被命名为 str.在 Python3 中使用 ·str 来代替 Python2 中的 unicode.

  10. Java RMI学习与解读(三)

    Java RMI学习与解读(三) 写在前面 接下来这篇就是最感兴趣的Attack RMI部分了. 前面也说过,RMI的通信过程会用到反序列化,那么针对于RMI的三个角色: Server/Regisrt ...