若果有一组硬币,(假定有十个),每一个硬币仅仅有两个面,正面用以表示。反面用零表示.

给定目标(初始状态)1111100000 正正正正正反反反反反

(目标状态)   1000011101 正反反反反正正正反正

规定每次仅仅能够翻转相邻的两个硬币(他们各自成为原来的对立面)

问题,至少用多少次就能够达到目的.

将每一种状态标记为,每一次的硬币翻动(1-9)状态i。都会使。当前状态变为还有一种状态状态i+1,假设在状态

i+1的位置,翻动和对应的位置,则会,回到状态i,因此推断是(状态与状态之间的转换)能够互相进行.以此推断图的搜索.

此处採索,

方法一

分析.

每一个硬币翻转后都会(且必须)影响一硬币,硬币个数大于一

考虑每次翻转都会有两个硬币翻转到相反状态,假设目标与初始有基数个不同样。就不能达到目标状态.

我们尽可能的是硬币当前硬币接近给定状态

因此从左向右,假设i号硬币与目标同样,跳过。否则翻转i,i+1号硬币.(i<n),翻转次数加一.

当到i==n是假设i号与目标同样则得到翻转次数.

否则不能通过有该翻转规则得到,由于有一个不同(1。是基数而该规则是,每次改变两个硬币).

问题是怎样证明最有性.

一个硬币假设被翻转偶数次相当与没有翻转

若被翻转多次,如果硬币i被翻转n次,相当于n%2次

那麽i-1,被翻转x次(相当于x%2),i+1被翻转了n-x次((n-x)%2)

x为偶数。n-x为奇数 n为奇数 翻转i和i+1

x为偶数 n-x为偶数 n也为偶数 相当于没有不论什么硬币被翻转

x为奇数 n-x为偶数 n为基数      相当于值翻转i-1,i

x为基数n-x为基数翻转了i-1,i+1.

通过上述四种情况我们发现能够对一个硬币有两种操作

1.翻转左右各一次(多次效果同样次数增多不是问题的解)使得相距一个的硬币翻转

2.翻转左边一次或者右边一次,效果都是使得相邻的硬币发生翻转

以以下情况举例说明2覆盖1

a.假如 要是0 0 0 翻转到 1 0 1

第一种翻转方法翻转两边使得达到结果次数为2

另外一种方法翻转1,2,使得达到效果结果次数为2

b.要是0 0 0 变为 1 1 0

第一种方式不能达到,而另外一种方式仅仅要翻转1。影响2(翻转2,影响1)就可以结果为1

由情况a,b能够看出要改变一个硬币仅仅需改变他和他相邻的硬币就可以.

相邻的有两边。那麽要改变硬币i,究竟要硬向那边,能够从第一个開始来推断是否i号须要被改变,那麽左边的都是完毕改变的,因此仅仅需顾虑右边就好了.

那可能会有疑问了,会不会从右边開始结果更少呢?

从两边開始结果一样的

非常明确的知道。全部翻转的点是与目标不同的点.如今有m个(m是偶数)由于已经证明结论基数个不同样硬币是不可能相邻翻转来改变是指同样。此时设有0<=i<j<=n;

a[i],a[j]都与目标不同样,此时从左向右还是从右翻转都是j-i次,那麽原硬币中有m个与终于结果不同样,此时可将这m开做k(o..m/2)的ik..jk.不同样的亮亮对,他们翻转操作次数

都是k(1...m/2) 求和ij-ik,因此偶数(可通过翻转到达的情况是从左到右从右到左是同样的).

比如记i号硬币起始情况与终于情况同样为1,否则为零那麽对以下的情况用上面的结论来计算结果.

1 0 1 0 0 0 1 0 1 0

从左向右(4-2)+ (6-5)+ (10 -8)= 5次

从右向左 (10-8) + (6-5) + (4-2) =5次

上面规律应征名,全部这杨m为偶数结果,从左向右,从右向左都同样。

以下解法即从左向右.

#include <stdio.h>
int main(){
int count=0,i;
int a[10];
int b[10];
for(i=0;i<10;i++){
scanf("%d",&a[i]);
}
for(i=0;i<10;i++){
scanf("%d",&b[i]);
}
for(i=0;i<9;i++){
if(a[i]!=b[i]){
a[i]=!a[i];
a[i+1]=!a[i+1];
count++;
}
}
printf("%d\n",a[i]==b[i]? count:-1);
return 0;
}

方法二

採取bfs,搜素状态树就可以.

要点两个:

1.状态的保存(判反复节点).若果节点反复则不应打开(去遍历他所相应的节点间)。

2.状态的表示,该题目的状态的表示,使用简单的哈希相应关系.

#include <iostream>
#include <cstring>
using namespace std;
const int size = 1000000+100;
typedef int state[10];
state st[size];
int vis[size]={0};
int dis[size]={0};
int getkey(state &s)
{
int i,adder=0;
for(i=0;i<10;i++){
adder=adder*2+s[i];
}
return adder;
}
int isvis(state &s){
int key=getkey(s);
if(vis[key])
return 1;
else {
vis[key]=1;
return 0;
}
}
int bfs(int front,int rear,state goal)
{
int i,j,k;
while(front!=rear){
state &s=st[front];
if(memcmp(goal,s,sizeof(s))==0)
return dis[front];
else{
for(i=0;i<9;i++){
state &t=st[rear]; memcpy(&t,&s,sizeof(s));
t[i]=!t[i];
t[i+1]=!t[i+1];
dis[rear]=dis[front]+1;
if(!isvis(t))
rear++;
}
}
front++;
}
return -1;
}
int main()
{
int front=1,rear=2,i,j,k;
state goal;
int distance=-1;
for(i=0;i<10;i++){
cin>>st[front][i];
}
for(i=0;i<10;i++){
cin>>goal[i];
}
distance=bfs(front,rear,goal);
cout<<distance<<endl;
return 0;
}

给出10个硬币初始状态,和终于状态得到最短反转步数.

log翻硬币的更多相关文章

  1. bzoj 3517: 翻硬币

    3517: 翻硬币 Time Limit: 1 Sec  Memory Limit: 128 MB Description 有一个n行n列的棋盘,每个格子上都有一个硬币,且n为偶数.每个硬币要么是正面 ...

  2. 51nod 1613翻硬币

    题目链接:51nod 1613 翻硬币 知乎上的理论解法http://www.zhihu.com/question/26570175/answer/33312310 本题精髓在于奇偶性讨论. 若 n ...

  3. HDU 3537 (博弈 翻硬币) Daizhenyang's Coin

    可以参考Thomas S. Ferguson的<Game Theory>,网上的博客大多也是根据这个翻译过来的,第五章讲了很多关于翻硬币的博弈. 这种博弈属于Mock Turtles,它的 ...

  4. hdu 3537(博弈,翻硬币)

    题意:给定了每个正面朝上的硬币的位置,然后每次可以翻1,2,3枚硬币,并且最右边的硬币开始必须是正面朝上的. 分析: 约束条件6:每次可以翻动一个.二个或三个硬币.(Mock Turtles游戏) 初 ...

  5. 翻硬币|2013年蓝桥杯B组题解析第八题-fishers

    翻硬币 小明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情形是:oooooo 如果同时翻转左 ...

  6. PREV-6_蓝桥杯_翻硬币

    问题描述 小明正在玩一个“翻硬币”的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情形是:**oo***oooo 如果同时翻转左边的两个 ...

  7. HDU 3537 基础翻硬币模型 Mock Turtles 向NIM转化

    翻硬币游戏,任意选3个,最右边的一个必须是正面.不能操作者败. 基本模型..不太可能自己推 还是老实记下来吧..对于单个硬币的SG值为2x或2x+1,当该硬币的位置x,其二进制1的个数为偶数时,sg= ...

  8. hdu 3537 翻硬币 每次能翻1个 或2个 或3个

    N 枚硬币排成一排,有的正面朝上,有的反面朝上.我们从左开始对硬币按1 到N 编号. 第一,游戏者根据某些约束翻硬币,但他所翻动的硬币中,最右边那个硬币的必须是从正面翻到反面. 第二,谁不能翻谁输. ...

  9. 算法笔记_194:历届试题 翻硬币(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 小明正在玩一个“翻硬币”的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情 ...

随机推荐

  1. vs调试MEX文件

    http://www.cnblogs.com/lukylu/p/4042306.html matlab里面无法单步调试mex函数,故需转到VS上面调试,这里采用VS2010. 参考网上很多人写的方法但 ...

  2. JavaSE学习总结第16天_集合框架2

      16.01 ArrayList存储字符串并遍历 ArrayList类概述:底层数据结构是数组,查询快,增删慢,线程不安全,效率高 ArrayList类是List 接口的大小可变数组的实现.实现了所 ...

  3. BZOJ 1019: [SHOI2008]汉诺塔( dp )

    dp(x, y)表示第x根柱子上y个盘子移开后到哪根柱子以及花费步数..然后根据汉诺塔原理去转移... ------------------------------------------------ ...

  4. 条款21: 必须返回对象时,不要强行返回对象的reference

    总结: 绝不要返回一个local栈对象的指针或引用:绝不要返回一个被分配的堆对象的引用:绝不要返回一个静态局部对象(为了它,有可能同时需要多个这样的对象的指针或引用). 条款4中给出了“在单线程环境中 ...

  5. YII2 使用js

    1.在 /backend/assets/ 中新建一个文件 CollectionAsset.php <?php /** * @link http://www.yiiframework.com/ * ...

  6. XIV

    http://publib.boulder.ibm.com/infocenter/ibmxiv/r2/index.jsp

  7. C++ ofstream和ifstream详细用法

    转载地址:http://soft.chinabyte.com/database/460/11433960.shtml ofstream是从内存到硬盘,ifstream是从硬盘到内存,其实所谓的流缓冲就 ...

  8. Windows Phone 8初学者开发—第5部分:布局和事件基础

    原文 Windows Phone 8初学者开发—第5部分:布局和事件基础 原文地址: http://channel9.msdn.com/Series/Windows-Phone-8-Developme ...

  9. 资源文件(.RES)的应用

    资源档有什麽用处呢?最重要的有两个地方1.国际发行:我们将Application中所有的文字从Resource用读取,那麽,只要更动            Resource档的内容,就可以用不同语言的 ...

  10. 警告:‘xxxx’ 将随后被初始化

    关于编译报警告.本次是接手一个新手的代码,总共不到1K行的代码.两个类.编译的时候报的警告,本来也不打算管理这个事情的.要求也不会有那么严格.但上午看完代码后,觉得毕竟是新手写的代码,还是有很多需要修 ...