[日常训练]翻转硬币
Description
$n$枚硬币正面朝上摆成一排,给定$a[1],a[2],…,a[m]$,每次操作可以翻转连续$a[i]$个硬币.要求经过最少次数的操作,使得仅第$x[1],x[2],…,x[k]$枚硬币反面朝上,输出最少次数.
Input
第一行三个整数$n,k,m$.
第二行$k$个整数表示需要反面朝上的硬币位置,从$1$编号.
第三行$m$个整数表示$a[1],a[2],…,a[m]$.
Output
一个整数表示答案,若无解,则输出$-1$.
Sample Input
10 8 2
1 2 3 5 6 7 8 9
3 5
Sample Output
2
HINT
$1\;\leq\;n\;\leq\;10^4,1\;\leq\;k\;\leq\;10,1\;\leq\;m\;\leq\;100,1\;\leq\;a[i]\;\leq\;n$.
Solution
因为每次翻转改变的是相邻两个硬币之间的相对状态.
所以用$b[i]$表示相邻两个硬币之间的相对状态($0$:状态相同;$1$状态不同).
初始状态和终止状态便可知了,现在要将终止状态还原回初始状态.
每当翻转$[x+1,x+a[i]]$(长度为$a[i]$)时,只对$b[x],b[x+a[i]]$产生影响.
当$b[x]=b[x+a[i]]=0$时,操作劣.
当$b[x]=b[x+a[i]]=1$时,可消掉两个元素.
当$b[x]=0,b[x+a[i]]=1$时,相当于$x+a[i]$移动到$x$.
所以先预处理出每个$b[i]=1$的$i$到其他$b[j]=1$的$j$的距离$g[i][j]$,状压$dp$即可.
$f[i]$为到达状态$i$(二进制表状态)所需最少步数.
因为每个元素早消晚消都得消,而且顺序没影响,
所以设$k$为使得$i\&(1$<<$k)=1$最大的$k$,
则$f[i-(1$<<$j)-(1$<<$k)]=min(f[i]+g[j][k])(i\&(1$<<$j)=1,j\;\not=\;k)$.
#include<cmath> #include<ctime> #include<queue> #include<stack> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define K 25 #define M 105 #define N 10005 #define F 1048576 #define INF 20000000 using namespace std; typedef long long ll; int g[K][K],f[F],a[M],p[K],dis[N],n,m,k,cnt=-1; bool b[N]; queue<int> q; inline void bfs(int u){dis[u]=0;q.push(u);while(!q.empty()){u=q.front();q.pop();for(int i=1;i<=m;++i){if(u-a[i]>=0&&dis[u]+1<dis[u-a[i]]){dis[u-a[i]]=dis[u]+1;q.push(u-a[i]);}if(u+a[i]<=n&&dis[u]+1<dis[u+a[i]]){dis[u+a[i]]=dis[u]+1;q.push(u+a[i]);}}} } inline void Aireen(){scanf("%d%d%d",&n,&k,&m);for(int i=1,j;i<=k;++i){scanf("%d",&j);b[j]=true;}for(int i=1;i<=m;++i)scanf("%d",&a[i]);for(int i=0;i<=n;++i)if(b[i]!=b[i+1])p[++cnt]=i;for(int i=0;i<F;++i)f[i]=INF;for(int i=0;i<=cnt;++i)for(int j=i+1;j<=cnt;++j)g[i][j]=g[j][i]=INF;for(int i=0;i<=cnt;++i){for(int j=0;j<=n;++j)dis[j]=INF;bfs(p[i]);for(int j=0;j<=cnt;++j)g[j][i]=g[i][j]=min(g[i][j],dis[p[j]]);}f[(1<<cnt+1)-1]=0;for(int i=(1<<cnt+1)-1,k;i;--i){for(k=cnt;k>=0;--k)if(i&(1<<k)) break;for(int j=0;j<=cnt;++j)if((i&(1<<j))&&j!=k) f[i-(1<<j)-(1<<k)]=min(f[i-(1<<j)-(1<<k)],f[i]+g[j][k]);}if(f[0]<INF) printf("%d\n",f[0]);else puts("-1"); } int main(){freopen("coin.in","r",stdin);freopen("coin.out","w",stdout);Aireen();fclose(stdin);fclose(stdout);return 0; }
转载于:https://www.cnblogs.com/AireenYe/p/6230700.html
[日常训练]翻转硬币相关推荐
- codeforces日常训练 C. Cutting Out - 二分搜索答案
codeforces日常训练 C. Cutting Out - 二分搜索答案 题干 You are given an array s consisting of n integers. You hav ...
- 试题 算法训练 翻转旋转变换
试题 算法训练 翻转旋转变换 资源限制 内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s 问题描述 现在有一张n行m列的由" ...
- DTOJ2548 翻转硬币
DTOJ2548 翻转硬币 题目 题目描述 输入格式 输出格式 样例 样例输入 样例输出 数据范围与提示 题解 题目 题目描述 nnn枚硬币正面朝上摆成一排,给定a1,a2,⋯,ama_1,a_2,\ ...
- 算法题 - 翻转硬币 - Python
问题描述: 翻转硬币 小明的面前有一块长度为N的正方形棋盘,共有N*N个方格,在棋盘的每个格子上都放有一块硬币,要么正面朝上(以0表示),要么背面朝上(以1表示). 小明可以任意选择一列,将列上的硬币 ...
- 蓝桥杯矩阵翻转java_矩阵翻转硬币 蓝桥杯
解题思路分析: n=2, m=3 翻硬币过程(1代表正面,0代表反面): step 1 : step 2 : 当(x, y) = (1, 1)时, (i * x, j * y)将 ...
- 「日常训练」Common Subexpression Elimination(UVa-12219)
今天做的题目就是抱佛脚2333 懂的都懂. 这条题目干了好几天,最后还是参考别人的代码敲出来了,但是自己独立思考了两天多,还是有收获的. 思路分析 做这条题我是先按照之前的那条题目(The SetSt ...
- 「日常训练」 Mike and Fun (CFR305D2B)
题意(CodeForces 548B) 每次对01矩阵中的一位取反,问每次操作后,单列中最长连续1的长度. 分析 非常非常简单,但是我当时训练的时候WA了四次...无力吐槽了,人间 不值得.jpg 代 ...
- 动规日常训练题解 难度普及+
9.6 动规训练 题解 ----Frosty_Jackal 定义Dpmax[i][j] 表示l~r之间最大的得分,由题意得拆环为链,将1~n的枚举范围扩大到1~2*n ,外层枚举区间长,内层枚举l, ...
- 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)
题意与分析(CodeForces 540D) 是一道概率dp题. 不过我没把它当dp做... 我就是凭着概率的直觉写的,还好这题不算难. 这题的重点在于考虑概率:他们喜相逢的概率是多少?考虑超几何分布 ...
最新文章
- AI 技术发展飞快,高校 AI 教师的知识储备能满足学生旺盛的求知欲吗?
- 阿里P8连肝一周整理出这份python自动化测试实战PDF
- Microsoft Office相关开发组件
- SQL JOIN --Merge Join
- php中html富文本编辑器,php + wangEditor 富文本编辑器的配置
- mysql有没有单机版?
- mybatis+spring mvc 完美整合方案 查询,保存,更新,删除自动生成
- 物联网专题--基于APP Inventor的BLE蓝牙4.0数据通信
- MyBatis自学(1):MyBatis概述
- OSI参考模型(1)
- Enterprise Library 1.0
- ArcGIS Server Image 扩展模块
- 免费微信公众号专用h5在线电影票API
- android 7 zip压缩文件,7-zip怎么把大文件压缩到最小
- c语言求闰年while,基础练习 闰年判断 c语言
- arcgis api 4.X 加载天地图3D
- 如何获取手机app的签名
- [BCE]光照传感器测量光照度-arduino程序
- 杰理之虚拟U盘升级【篇】
- 【BZOJ】1535: [POI2005]Sza-Template