csdn英雄会题解之翻纸牌游戏__hdu2209

题目描述 有一种纸牌游戏,很有意思,给你N张纸牌,一字排开,纸牌有正反两面,开始的纸牌可能是一种乱的状态(有些朝正,有些朝反),现在你需要整理这些纸牌。但是麻烦的是,每当你翻一张纸牌(由正翻到反,或者有反翻到正)时,他左右两张纸牌(最左边和最右边的纸牌,只会影响附近一张)也必须跟着翻动,现在给你一个乱的状态,问你能否把他们整理好,使得每张纸牌都正面朝上,如果可以,最少需要多少次操作。 输入 有多个case,每个case输入一行01符号串(长度不超过20),1表示反面朝上,0表示正面朝上。 输出 对于每组case,如果可以翻,输出最少需要翻动的次数,否则输出NO。

我的做法:

每张扑克牌有主动翻和主动不翻(主动翻两次相等于主动不翻)两种情况,那么总共有2^n方种情况,如果这2^n方中情况中仍不能找到使其都为正面朝上,那么肯定就找不到了,因为再继续找下去,肯定会出现某个主动翻两次,又转换为2^n方内的情况了。采用DFS搜索所有情况:

代码为:

#include
#include
#include
#include 
#include 
const int maxn=20;
bool flag[maxn];//是否主动翻动过
int times=INT_MAX;

bool isOk(const std::string &str){//所有扑克是否正面向上
	if(std::string::npos==str.find_first_of('1'))
		return true;
	else
		return false;
}
void initFlag(){//
	for(std::size_t i=0;i=2
void getMin(std::string& str,int depth){
	if(depth==str.size()){
		if(isOk(str)){
			int res=countFlag(str.size());
			if(res0)
		turn(str[depth-1]);
	turn(str[depth]);
	if(depth+10)
		turn(str[depth-1]);
	turn(str[depth]);
	if(depth+1>str){
		times=INT_MAX;
		initFlag();
		getMin(str,0);
		if(times!=INT_MAX)
			std::cout<


由于depth只会影响到depth-1,depth,depth+1,所以如果depth-1以前有反面向上,那么,最后isOk肯定是false,可以进行减枝,代码修改为:

void getMin(std::string& str,int depth){
	if(depth==str.size()){
		if(isOk(str)){
			int res=countFlag(str.size());
			if(res=2){
		if(str[depth-2]=='1')
			return ;
	}
	getMin(str,depth+1);
	if(depth>0)
		turn(str[depth-1]);
	turn(str[depth]);
	if(depth+10)
		turn(str[depth-1]);
	turn(str[depth]);
	if(depth+1


此方法在hdu提交成功,在hero提交提示代码异常,不知道为什么了,调了半天!

还可以通过depth步为了确保depth-1为正面向上而主动翻动来进行优化。可以参见http://blog.csdn.net/xingyeyongheng/article/details/9627625


你可能感兴趣的:(CSDN英雄会题解,csdn英雄会题解,翻纸牌游戏,翻纸牌,hdu2209,hdu翻纸牌游戏)