[ACM训练] 算法初级 之 基本算法 之 枚举(POJ 1753+2965)

先列出题目:

1、POJ 1753

POJ 1753  Flip Game:http://poj.org/problem?id=1753

Sample Input

bwwb
bbwb
bwwb
bwww

Sample Output

4

入手竟然没有思路,感觉有很多很多种情况需要考虑,也只能使用枚举方法才能解决了吧~

4x4的数组来进行数据存储的话操作起来肯定非常不方便,这里借用位压缩的方法来存储状态,使用移位来标识每一个位置的的上下左右的位置操作。 详细看这里

1、当棋盘状态id为0(全白)或65535(全黑)时,游戏结束,0^1=1,1^1=0,所以翻转的操作可以通过异或操作来完成,而翻转的位置可以通过移位来确定。

2、结束标识!!!!!

分步骤:

1、从输入到位标识状态:

 1     int state = 0;
 2     char ch[4];
 3
 4     while(cin>>ch)
 5     {
 6        for(int j = 0 ; j < 4 ; j++)
 7         {
 8             state = state<<1;
 9             if(ch[j] == ‘b‘)
10                 state += 1;
11         }
12     }

2、从一个状态到下一个状态的的转换,比如对应位置i处进行改变后得到的状态:

这里的16个数据使用代码生成可能是想不到的,但是可以通过手动变换一次获得~~~

 1 int change[16] ={
 2      51200,58368,29184,12544,
 3      35968,20032,10016,4880,
 4      2248,1252,626,305,
 5      140,78,39,19
 6 };
 7
 8 state = state^change[i];//对应第i个位置的改变
 9
10 //上面的16个数据是由下面的代码得来的
11
12 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
13 void init()
14 {
15     int i,j,x,y,t,temp;
16     for(i=0;i<4;++i)
17     {
18         for(j=0;j<4;++j)
19         {
20             temp = 0;
21             temp ^= (1<<((3-i)*4+3-j));   //第一行代表16位的高4位,同理第一列也代表高位,所以棋盘(i,j)处在16位中的位置是((3-i)*4+3-j)
22
23             for(t=0;t<4;++t)
24             {
25                 x = i + dir[t][0];
26                 y = j + dir[t][1];
27                 if(x<0 || y<0 || x>3 || y>3)
28                     continue;
29                 temp ^= (1<<((3-x)*4+3-y));
30             }
31             cout<<temp<<" ";
32         }
33         cout<<endl;
34     }
35 }

3、判断是否满足情况只需要判断state == 0 || state == 65535 即可。

4、解决了小问题,再思考一下大逻辑:

初始状态即为纯色则直接输出0,初始不是纯色,翻转一个的状态是纯色,则输出1,翻转一个会产生n种状态,0<=n<=16,这些状态要放入到队列中进行保存,再从中出队列再进行下一次的翻转。关键问题是什么情况下判定翻转结束,仍然没有纯色出现,则输出impossible,大于2次的翻转的初态都是从队列中取出来的,必须提前设计一个状态标识,表明同一种状态不再次进行入队列,那么当队列为空时才可以下结论。

 1 //需要设置一个是否处理过的标识,共有状态有65536个,即0-65535,
 2 //如果对应位置被标记为1了,则说明已经处理过,直接抛弃进行下一次
 3
 4 //这样的遍历过程被称为BFS的过程
 5
 6
 7 bool visit[65536];
 8
 9 int bfs(int state)//返回值是进行的步数,impossible为-1
10 {
11     queue<Node> q;
12     Node current,next;
13
14     current.state = state;
15     current.step = 0;
16     q.push(current);
17     visited[state] = true;
18
19     while(!q.empty())
20     {
21         current = q.front();
22         q.pop();
23
24         if(current.state == 0 || current.state == 65535)
25             return current.step;
26
27         for(int i = 0;i<16;i++)//每一种状态都要进行16次操作
28         {
29             next.state = current.state^change[i];
30             next.step = current.step+1;
31
32             if(next.state == 0 || next.state == 65535)
33                 return next.step;
34             else
35             {
36                 if(visited[next.state])
37                     continue;
38                 else
39                 {
40                     visited[next.state] = true;
41                     q.push(next);
42                 }
43             }
44         }
45     }
46     return -1;
47 }

总结:枚举,此题就是使用枚举的思想来找到需要的解,尤其是使用队列来进行一个的while循环来进行的。

下一个类似的题目是POJ的2965题目:The Pilots Brothers‘ refrigerator http://poj.org/problem?id=2965

Sample Input

-+--
----
----
-+--

Sample Output

6
1 1
1 3
1 4
4 1
4 3
4 4
时间: 2024-10-13 18:34:05

[ACM训练] 算法初级 之 基本算法 之 枚举(POJ 1753+2965)的相关文章

ACM训练-floyd算法

问题描述:多源点问题和负权值图的最短路径 算法描述:Floyd算法是一个经典的动态规划算法.从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j.所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完

算法&lt;初级&gt; - 第五章 递归与动规相关问题(完结)

算法<初级> - 第五章 递归与动规相关问题(完结) <一>递归和动态规划 暴力递归 转化为规模缩小了的同问题的子问题 - 时间复杂度O(2n-1) 有明确的边界条件(base case) - 先写base case,再写问题递归的过程 有得到子问题结果后决策过程 不记录每个子问题的解 - 每次求解子问题都交给递归去解决,不会在全局保存子问题的解(与动规形成对比) 动态规划DP 从暴力递归中延申 - 过程中还经历过<记忆化搜索>,相当于暴力递归+cache缓存(用has

2014暑假ACM训练总结

2014暑假ACM训练总结报告 匆匆之中,一个暑假又过去了,在学校训练的这段日子真的是感觉日子过得好快啊! 时光如箭,日月如梭! 匆忙的学习之中一个暑假就这样结束了,现在就来写一些总结吧,供自己以后阅读和回忆吧! 2014年7月14我们即可1303考完了最后一科模拟电路,也宣告了暑假的到来!本来有刚好两 星期的时间可以回家或是去做其他的事,然后我在学校呆了几天,无聊之余便回家了.在家呆了大概 7天,便正式回校了,准备学校的ACM的训练去了. 先亮一下暑假的训练计划吧! 集训详情: 第一周回顾知识

ACM训练方案-POJ题目分类

ACM训练方案-POJ题目分类 博客分类: 算法 ACM online Judge 中国: 浙江大学(ZJU):http://acm.zju.edu.cn/ 北京大学(PKU):http://acm.pku.edu.cn/JudgeOnline/ 杭州电子科技大学(HDU):http://acm.hdu.edu.cn/ 中国科技大学(USTC):http://acm.ustc.edu.cn/ 北京航天航空大学(BUAA)http://acm.buaa.edu.cn/oj/index.php 南京

ACM训练二C题

kmp对我真无奈,我对kmp真苦恼.就是个算法嘛,我以为凭我脖子上的东西可以搞定,现在好了--搞得我头都大了.要我写个啥next的值,五个字:那都不是事.一到啥实际应用吧,我意识不行了,搞不清next到底有什么作用,能干什么.就好比见到了二分啊-- 此题的意思呢,我弄了很久,其实是找相同串,比如ACMACMACMACMACMA,从后往前看next就行了,比如最后一个next[15] = 13,代表前13个字符串和后13位相同,直接用总长16 - 13 = 3,为一个解,接下来看next[13]了

决策树-预测隐形眼镜类型 (ID3算法,C4.5算法,CART算法,GINI指数,剪枝,随机森林)

1. 1.问题的引入 2.一个实例 3.基本概念 4.ID3 5.C4.5 6.CART 7.随机森林 2. 我们应该设计什么的算法,使得计算机对贷款申请人员的申请信息自动进行分类,以决定能否贷款? 一个女孩的母亲要给这个女孩介绍男朋友,于是有了下面的对话: 女儿:多大年纪了? 母亲:26. 女儿:长的帅不帅? 母亲:挺帅的. 女儿:收入高不? 母亲:不算很高,中等情况. 女儿:是公务员不? 母亲:是,在税务局上班呢. 女儿:那好,我去见见. 决策过程: 这个女孩的决策过程就是典型的分类树决策.

machine_learning-knn算法具体解释(近邻算法)

近邻算法是机器学习算法中的入门算法,该算法用于针对已有数据集对未知数据进行分类. 该算法核心思想是通过计算预測数据与已有数据的相似度猜測结果. 举例: 如果有例如以下一组数据(在下面我们统一把该数据作为训练数据): 身高 年龄 国籍 170 23 中国 180 21 美国 185 22 俄国 175 24 中国 120 23 日本 我们将该组数据的前两列作为一个特征值.最后一项作为一个待分类结果.当数据量足够大时,能够通过该数据便可得出较为精确的分类. 比如我们拿到測试数据.年龄23岁,身高17

ACM训练和应用开发的体验,大二学生可以并行开展

[来信] 老师 我现在是大二的一名学生 我们专业虽然是计算机专业但是这届大一才真是和其他计算机专业一样开始大一上C语言 C 我们这级仍然是大二开的C语言和数据结构 我在学校做过一段时间ACM 70道题 但是最近我又开始去学windows的程序设计 不知道为什么总感觉学起来力不从心 我现在学完了C C 和数据结构 我接下来到底做什么好呢 [回复:(原回复找不到了,CSDN的私信功能应该出问题了,不按时间排序.我指出他的行文中没有标点,我读得很费劲.另外,他的具体情况,需要给我说明.)] [再来信]

opencv3中的机器学习算法之:EM算法

不同于其它的机器学习模型,EM算法是一种非监督的学习算法,它的输入数据事先不需要进行标注.相反,该算法从给定的样本集中,能计算出高斯混和参数的最大似然估计.也能得到每个样本对应的标注值,类似于kmeans聚类(输入样本数据,输出样本数据的标注).实际上,高斯混和模型GMM和kmeans都是EM算法的应用. 在opencv3.0中,EM算法的函数是trainEM,函数原型为: bool trainEM(InputArray samples, OutputArray logLikelihoods=n