标签:表示 记录 count array false round ffffff ring 因此
例1:计算24点
输入4张牌,输出一个算式,算式的结果为24点。
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> using namespace std; #define COUNT 4 #define EPS 1e-6 char fuhao[3]; int number[COUNT]; int newArray[COUNT]; bool find; //2.因为这里面有double类型的数学计算,因此保险用这种方式判断两个数是否相同 bool iszero(double x){ return fabs(x)<=EPS; } //第3步:计算a数组的前n个数字进行排列组合后能否得到值为expect,注意expect表示期望得到的值,是一个double类型 // 是一个递归调用,从后向前先固定一个运算符 + 最后一个运算数,然后知道自己希望前面几个运算数经过组合得到的值应该是多少,所以递归计算 bool caculate(int a[COUNT], int n, double expect){ int index=n-1; bool isexpect; if(index==0){ if(iszero(a[index]-expect))return true; else return false; } fuhao[index-1]=‘+‘; isexpect=caculate(a,index,expect-a[index]); if(isexpect) return true;
fuhao[index-1]=‘-‘; isexpect=caculate(a,index,expect+a[index]); if(isexpect) return true;
fuhao[index-1]=‘*‘; isexpect=caculate(a,index,expect/a[index]); if(isexpect) return true;
fuhao[index-1]=‘/‘; isexpect=caculate(a,index,expect*a[index]); if(isexpect) return true;
return false; } char getOutChar(int i){ char tmp; switch (i){ case 11: tmp=‘J‘;break; case 12: tmp=‘Q‘;break; case 13: tmp=‘K‘;break; case 1: tmp=‘A‘;break; default: tmp=i+‘0‘; } return tmp; } //第2步:对输入的数据进行组合排序,核心算法为: // 利用一个循环,轮流做新组合的第1把交椅,固定第一把交椅后, // 再从剩下的数字中轮流做剩下交椅中的第一把交椅(递归) // 但是这里需要注意的是,所谓剩下的数字不是"之后的数字",而是"剩下的数字",所以需要用一个数组来标识哪个数字已经坐上交椅了。 char used[COUNT]; //用来记录在组合排序的时候 是否已经算进来了 bool permuteAndCaculate(int pos, const int n,const int r) { int i; bool find=false; if(pos == r){ //如果已经是第r个元素了,则可打印r个元素的排列 if(caculate(newArray,r,24)){ for(i=0; i<r-1; i++){ if(newArray[i]==10) cout << 10; else cout << getOutChar(newArray[i]); cout << fuhao[i]; } if(newArray[r-1]==10) cout <<10; //单独打印,因为最后一个数字后面没有符号 else cout << getOutChar(newArray[i]);
cout<<endl; return true; } return false; } for (i=0; i<n; i++){ if(!used[i]){ newArray[pos]=number[i]; used[i] = 1; /*递归搜索,得到后续元素 */ find=permuteAndCaculate(pos+1,n,r); /*恢复递归前的值,目的是使以后该元素可作为后续元素使用*/ used[i] = 0; if(find) //如果在深层递归中已经找到了满足条件的。那么也不需要继续计算了 break; } } return find; } int main(){ char a[COUNT][10]; int result[COUNT]; //while(scanf("%s %s %s %s %s",a[0],a[1],a[2],a[3],a[4])!=EOF){ while(scanf("%s %s %s %s",a[0],a[1],a[2],a[3])!=EOF){ bool iserror=false; //注意一定在这里重置一下,否则上一轮的测试可能将他初始值变更 //第1步:check valid for(int i=0; i<COUNT; i++){ //if(strcmp(a[i],"joker")==0 || strcmp(a[i],"JOKER")==0){ //注意这里面假设真正的扑克牌,即大小王固定,且不会出现数字0等怪异字符 if(strlen(a[i])>2){ //joker or JOKER //如果保险起见,还是应该这样的判断逻辑才对 iserror=true; break; //最好不要直接return,for next scan } else if(strlen(a[i])==2&&a[i][0]==‘1‘&&a[i][1]==‘0‘) number[i]=10; else if(strlen(a[i])==1){ if(a[i][0]>‘0‘&&a[i][0]<=‘9‘) number[i]=a[i][0]-‘0‘; else{ switch(a[i][0]){ case ‘J‘:number[i]=11; break; case ‘Q‘:number[i]=12; break; case ‘K‘:number[i]=13; break; case ‘A‘:number[i]=1; break; default: iserror=true; break; } if(iserror) break; } } else{ iserror=true; break; } }
//第2,3步:计算 if(iserror) cout <<"ERROR"<<endl; else{ if(!permuteAndCaculate(0,COUNT,COUNT)) cout << "NONE"<<endl; //结束换行符很重要 } } return 0; }
例2:计算数独
玩家需要根据9X9盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个粗线宫内的数字均含1-9,并且不重复。
核心算法:如果该空格是该行或者该列的唯一一个空格,则直接固定;否则先固定一个值递归计算剩下是否合法;
剩下的是否合法也是使用这样的方式,如果递归发现剩下的确定不合法则返回到上层,换成下一个值。
另外,不能随便固定一个值,必须是符合要求的,即不能是和其他格中相同的数字,算法是:
遍历当前行/列/小框框,看看新放置的这个数字是否合法,即是否在这一行中已经存在了
按照上面的逻辑,一共是9宫格,又只有1-9的9个数字,所以一路下来,如果都能不重复的填进坑,则刚好
标签:表示 记录 count array false round ffffff ring 因此
原文地址:https://www.cnblogs.com/shuiguizi/p/12343951.html