翻硬币的伪代码实现

来源:互联网 发布:linux crontab每月 编辑:程序博客网 时间:2024/04/28 09:24

题目描述:

一个翻硬币的游戏,有N(N <=10000)行硬币,每行有九个硬币,排成一个N*9的方阵,有的硬币正面朝上,有的反面朝上。我们每次可把一整行或者一整列的所有硬币翻过来,请问怎么翻,使得正面朝上的硬币尽量多(翻硬币无次数限制)。

 

思路分析:

枚举2^9种列的翻法。 
遍历N行,如果某行正面朝上的少,翻之;如果正面朝上的多,不翻 
记下使得正面最多的方法即可 
耗时O(2^9 * N)

这个得到的是最优解.用位运算效率还是很高的. 
对每一列,都用一个9位的数表示,一共有N个 
然后便利所有的9位状态,(000000000)-(111111111) (二进制) 
对于每个状态,都与这N个数异或,每次异或后累加所有的1的值假设为k,如果k小于5则k=9-k. 
对N个数累加所有的k,得到最终累加和. 

求出所有状态下累加和最大的,就是正面朝上的硬币尽量多的个数. 
翻面的方法横列分别是最优解的8位状态和与之对应的每个数异或后累加和k是否小于5.



上面是从别人博客看到的

下面贴上我的伪代码

A数组用来存放硬币,数值1代表正面,0代表反面;

static int s;s是存放每列状态的数初始为0代表一列都没翻,第几位为1就代表第几列被翻转

int turncoin(A,S,N,n) //A(N*9数组) ,N是行数 n代表当次翻哪一列 初次调用n=0,代表第一列 

{ int i=1;//因为每列只有两种状态,所以每列只翻一次

static int max=0;//用来存放翻转后正面朝上的最大硬币数;

static int S;//大S用来存储当前硬币堆的翻转状态

do {

turncoin(A,S,N,n+1);

if (n==8)

{ int tem=sum //sum为遍历A数组,所有元素之和(即为当前正面朝上的硬币数)

if(sum>max){

S=s; //把当前翻转状态存储到S,S内总是存储着拥有正面朝上硬币数量最高的一种翻转状态;

}

}

}while(i--&&transform(N,n));   //transform()函数翻转第N列的硬币 并且对s的第n位置一 成功返回ture 并且对是 实现就是for(i=0;i<N)对取反A[i][n]赋给自身   注意考虑这里的&&短路求值

return  S;   //好了 这里S根据S每一位就得道最终所要求的结果

}