DTOJ2548 翻转硬币

  • 题目
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例
      • 样例输入
      • 样例输出
    • 数据范围与提示
  • 题解

题目

题目描述

nnn枚硬币正面朝上摆成一排,给定a1,a2,⋯,ama_1,a_2,\cdots,a_ma1​,a2​,⋯,am​,每次操作可以翻转连续aia_iai​个硬币。要求经过最少次数的操作,使得仅第x1,x2,⋯,xkx_1,x_2,\cdots,x_kx1​,x2​,⋯,xk​枚硬币反面朝上,输出最少次数

输入格式

第一行三个整数n,k,mn,k,mn,k,m
第二行kkk个整数表示需要反面朝上的硬币位置,从111编号
第三行mmm个整数表示a1,a2,⋯,ama_1,a_2,\cdots,a_ma1​,a2​,⋯,am​

输出格式

一个整数表示答案,若无解,则输出−1-1−1

样例

样例输入

10 8 2
1 2 3 5 6 7 8 9
3 5

样例输出

2

数据范围与提示

对于30%30\%30%的数据,n,m⩽10n,m\leqslant 10n,m⩽10
对于60%60\%60%的数据,m⩽20m\leqslant 20m⩽20
对于100%100\%100%的数据,1⩽n⩽10000,1⩽k⩽10,1⩽m⩽100,1⩽a[i]⩽n1\leqslant n\leqslant 10000,1\leqslant k\leqslant 10,1\leqslant m\leqslant100,1\leqslant a[i]\leqslant n1⩽n⩽10000,1⩽k⩽10,1⩽m⩽100,1⩽a[i]⩽n

题解

因为每次翻转改变的是相邻硬币相对的状态
所以我们用did_idi​表示相邻硬币相对的状态,即000表示状态相同,111表示状态不同
现在,假设我们翻转[x+1,x+ai)[x+1,x+a_i)[x+1,x+ai​),那么,我们只会影响dxd_xdx​和bx+aib_{x+a_i}bx+ai​​,有三种情况:

  1. dx=dx+ai=0d_{x}=d_{x+a_i}=0dx​=dx+ai​​=0:这个翻转没啥用
  2. dx=dx+ai=1d_{x}=d_{x+a_i}=1dx​=dx+ai​​=1:两个都变成000
  3. dx=0,dx+ai=1d_{x}=0,d_{x+a_i}=1dx​=0,dx+ai​​=1:就相当于是把x+aix+a_ix+ai​移到了xxx

所以我们可以先预处理出每个di=1d_i=1di​=1的iii到其他dj=1d_j=1dj​=1的jjj的距离gi,jg_{i,j}gi,j​
然后我们就可以状压状压dpdpdp了
我们用fsf_sfs​为到达状态sss所需最少次数
我们假设sss中为111的位最大是kkk(即最大的满足i&2k=1i\&2^k=1i&2k=1的kkk),那么fs−2j−2k=min{fs+gj,k}f_{s-2^j-2^k}=min\{f_{s}+g_{j,k}\}fs−2j−2k​=min{fs​+gj,k​},其中,jjj是sss中为111的位,且j≠kj\neq kj​=k
附上代码:

#include<cstring>
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n,m,k,nd=-1,c[10010],a[110],d[30],f[1048580],g[30][30],dis[10010];
queue<int> q;
void bfs(int x)
{dis[x]=0,q.push(x);while(!q.empty()){x=q.front(),q.pop();for(int i=1;i<=m;i++){if(x-a[i]>=0&&dis[x]+1<dis[x-a[i]]) dis[x-a[i]]=dis[x]+1,q.push(x-a[i]);if(x+a[i]<=n&&dis[x]+1<dis[x+a[i]]) dis[x+a[i]]=dis[x]+1,q.push(x+a[i]);}}
}
int main()
{//  freopen("coin.in","r",stdin);
//  freopen("coin.out","w",stdout);scanf("%d%d%d",&n,&k,&m);for(int i=1,j;i<=k;i++) scanf("%d",&j),c[j]=1;for(int i=1;i<=m;i++) scanf("%d",&a[i]);for(int i=0;i<=n;i++) if(c[i]!=c[i+1]) d[++nd]=i;for(int i=0;i<=1048576;i++) f[i]=100000000;for(int i=0;i<=nd;i++) for(int j=0;j<=nd;j++) g[i][j]=100000000;for(int i=0;i<=nd;i++){for(int j=0;j<=n;j++) dis[j]=100000000;bfs(d[i]);for(int j=0;j<=nd;j++) g[j][i]=g[i][j]=min(g[i][j],dis[d[j]]);}f[(1<<nd+1)-1]=0;for(int i=(1<<nd+1)-1,k;i;i--){for(k=nd;k>=0;--k) if(i&(1<<k)) break;for(int j=0;j<=nd;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]<100000000) printf("%d",f[0]);else printf("-1");
}

DTOJ2548 翻转硬币相关推荐

  1. 算法题 - 翻转硬币 - Python

    问题描述: 翻转硬币 小明的面前有一块长度为N的正方形棋盘,共有N*N个方格,在棋盘的每个格子上都放有一块硬币,要么正面朝上(以0表示),要么背面朝上(以1表示). 小明可以任意选择一列,将列上的硬币 ...

  2. 蓝桥杯矩阵翻转java_矩阵翻转硬币 蓝桥杯

    解题思路分析:           n=2, m=3 翻硬币过程(1代表正面,0代表反面): step 1 : step 2 : 当(x, y) = (1, 1)时, (i * x,  j * y)将 ...

  3. [日常训练]翻转硬币

    Description $n$枚硬币正面朝上摆成一排,给定$a[1],a[2],-,a[m]$,每次操作可以翻转连续$a[i]$个硬币.要求经过最少次数的操作,使得仅第$x[1],x[2],-,x[k ...

  4. 归纳算法——硬币翻转问题

    题:有任意N个硬币正面朝上,每次翻转n个硬币知道将N个硬币全部翻转成反面.(*表示正面,0表示反面) 源代码如下: /* **翻转硬币问题,设共有N个硬币,一次允许翻转n<N个,需翻转x步,每个 ...

  5. java硬币翻转问题_java – 硬币翻转程序

    我尝试制作一个翻转硬币的程序(首先显示头部图像,然后显示尾部图像),当我遇到问题时,我遇到了试图查看硬币图像的问题;只显示一个空白屏幕.我不知道这是来自jpg图像的不正确保存方法还是来自代码中的错误. ...

  6. 【牛客 - 373A】翻硬币问题(博弈,结论,分析)

    题干: 链接:https://ac.nowcoder.com/acm/contest/373/A 来源:牛客网 Alice和Bob正在玩一个很经典的游戏. 有 n n个硬币初始时全部正面朝上,每一轮A ...

  7. HDOJ 3537 Daizhenyang's Coin (翻硬币游戏)

    转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove 每次可以翻动一个.二个或三个硬币. ...

  8. 数据结构-16枚硬币问题

    数据结构-16枚硬币问题 本题主要考查对图的结构和图的广度优先遍历操作的掌握. 实现效果: 什么是图? 定义:图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其 ...

  9. 假设检验怎么做?这次把方法+Python代码一并教给你

    (图片付费下载于视觉中国) 作者 | Jose Garcia 译者 | 张睿毅 校对 | 张一豪.林亦霖 编辑 | 于腾凯 来源 | 数据派THU(ID:DatapiTHU) [导读]本文中,作者给出 ...

最新文章

  1. petalinux 安装 库 时的问题
  2. RabbitMQ配置环境变量后启动不了的解决方法
  3. 输出和为n的所有的连续自然数序列
  4. springcloud @EnableDiscoveryClient注解作用
  5. tomcat 相关以及安装时遇到的一些问题整理
  6. maven3安装和使用笔记
  7. 从外部访问Kubernetes集群中的应用
  8. XML与HTML区别
  9. 基于GAN的手写数字生成实践
  10. 得力计算机1526弹音乐,得力1526计算器乐谱 | 手游网游页游攻略大全
  11. SPSS多元线性回归及逐步回归学习笔记
  12. 什么叫DMZ区?DMZ区它有什么作用?
  13. 您没有权限访问网络计算机,Win7提示“无法访问您可能没有权限使用网络资源”如何解决?...
  14. If today were the last day of my life
  15. 一睹64位Windows XP的芳容(也是从网上copy的,扫了一下,没有仔细看)
  16. 有趣的姓名小知识:你身边有叫沐宸和若汐的宝宝吗?
  17. 机器学习入门1-译文-机器学习是什么以及它的重要性(machine learning--what it is and why it matters)
  18. python怎么读数据_Python如何读取数据
  19. KISSY基础篇乄KISSY之IO(2)
  20. dll文件下载安装网站

热门文章

  1. 如何实现搜索历史记录
  2. XGBoost和Boosted Trees
  3. 【Android】逆向自动化
  4. jsp去掉input边框_详解移动端HTML5页面端去掉input输入框的白色背景和边框(兼容Android和ios)...
  5. PytorchStreamReader failed reading zip archive: failed finding central directory
  6. Android记录手机屏幕操作并进行回放(需要root权限)
  7. TOEFL阅读——长难句专项训练17
  8. Vm挂载虚拟硬盘(手把手教程)
  9. (转)Proxy error: Could not proxy requestXXX from localhost:8080 to localhost:3000 (ENOTFO
  10. 如何搭建知识付费平台