HDU 1427 速算24点-DFS
Related: Compute 24 每日一题(13)――24点 (分治&递归)
http://java-mans.iteye.com/blog/1642726
https://moonstonelin.wordpress.com/2016/04/06/caculate-24/
http://www.voidcn.com/blog/u014664226/article/p-4336216.html
Related: Compute 24 每日一题(13)――24点 (分治&递归)
速算24点相信绝大多数人都玩过。就是随机给你四张牌,包括A(1),2,3,4,5,6,7,8,9,10,J(11),Q(12),K(13)。要求只用'+','-','*','/'运算符以及括号改变运算顺序,使得最终运算结果为24(每个数必须且仅能用一次)。游戏很简单,但遇到无解的情况往往让人很郁闷。你的任务就是针对每一组随机产生的四张牌,判断是否有解。我们另外规定,整个计算过程中都不能出现小数。
Input
每组输入数据占一行,给定四张牌。
Output
每一组输入数据对应一行输出。如果有解则输出"Yes",无解则输出"No"。
Sample Input
A 2 3 6 3 3 8 8
Sample Output
Yes No
枚举数字和运算符,DFS即可,注意题目要求计算过程中都不能出现小数,所以做除法时稍作处理
枚举数组可用algorithm里的next_permutation
The next_permutation() function attempts to transform the given range of elements [start,end) into the next lexicographically greater permutation of elements. If it succeeds, it returns true, otherwise, it returns false.
http://www.xuebangwang.com/article-7594-1.htmlvoid dfs(int sum,int next,int p) //表示当前已经算出的值是sum,括号中算出的值是next,当前使用的卡片下标为p { if(p==4) //正在用第4张牌 { if(sum+next==24||sum-next==24||sum*next==24) flag=true; if(next!=0&&sum%next==0&&sum/next==24) flag=true; return; } //1、不加括号 dfs(sum+next,cardNum[p+1],p+1); dfs(sum-next,cardNum[p+1],p+1); dfs(sum*next,cardNum[p+1],p+1); if(next!=0&&sum%next==0) dfs(sum/next,cardNum[p+1],p+1); //2、加括号,则需要改变运算顺序 dfs(sum,next+cardNum[p+1],p+1); dfs(sum,next-cardNum[p+1],p+1); dfs(sum,next*cardNum[p+1],p+1); if(cardNum[p+1]!=0&&next%cardNum[p+1]==0) dfs(sum,next/cardNum[p+1],p+1); }
http://blog.csdn.net/u014492609/article/details/40268385sort(cardNum+1,cardNum+5); do { dfs(cardNum[1],cardNum[2],2); }while(!flag&&next_permutation(cardNum+1,cardNum+5));
http://java-mans.iteye.com/blog/1642726
- int num[4];
- int cmp(const void *a,const void *b)
- {
- return *(int *)a-*(int *)b;
- }
- void dfs(int sum,int cur,int m)
- {
- if(flag)
- return;
- if(m==3)
- {
- if(sum+cur==24||sum-cur==24||sum*cur==24)
- flag=1;
- if(cur!=0&&sum%cur==0&&sum/cur==24)
- flag=1;
- return;
- }
- dfs(sum+cur,num[m+1],m+1); //先计算前一部分
- dfs(sum-cur,num[m+1],m+1);
- dfs(sum*cur,num[m+1],m+1);
- if(cur!=0&&sum%cur==0)
- dfs(sum/cur,num[m+1],m+1);
- dfs(sum,cur+num[m+1],m+1); //先计算后一部分,相当于加括号
- dfs(sum,cur-num[m+1],m+1);
- dfs(sum,cur*num[m+1],m+1);
- if(num[m+1]!=0&&cur%num[m+1]==0)
- dfs(sum,cur/num[m+1],m+1);
- }
- qsort(num,4,sizeof(num[0]),cmp);
- flag=0;
- do
- {
- dfs(num[0],num[1],1);
- }while(next_permutation(num,num+4)&&!flag);
- if(flag)
- printf("Yes\n");
- else
- printf("No\n");
https://moonstonelin.wordpress.com/2016/04/06/caculate-24/
public List<string> Generate 24 (int[] cards) { List<string> result = new List<string>(); Dictionary<string, int> dict = GenerateHelper(cards); foreach (var kp in dict) { if (!result.Contains(kp.Key) && (kp.Value == 24 )) { result.Add(kp.Key); } } return result; } private Dictionary<string, int> GenerateHelper(int[] cards) { Dictionary<string, int> dict = new Dictionary<string, int>(); if (cards.Length == 1 ) { dict.Add(cards[ 0 ].ToString(), cards[ 0 ]); } if (cards.Length == 2 ) { this.AddEntries(dict, cards[ 0 ].ToString(), cards[ 1 ].ToString(), cards[ 0 ], cards[ 1 ]); } if (cards.Length == 3 ) { List<int> cards 1 = new List<int>(); List<int> cards 2 = new List<int>(); for (int i = 0 ; i <= 2 ; i++) { Swap(cards, 0 , i); Dictionary<string, int> dict 1 = GenerateHelper(new int[]{ cards[ 0 ] }); Dictionary<string, int> dict 2 = GenerateHelper(new int[] { cards[ 1 ], cards[ 2 ] }); this.Construct(dict, dict 1 , dict 2 ); } } if (cards.Length == 4 ) { List<int> cards 1 = new List<int>(); List<int> cards 2 = new List<int>(); for (int i = 0 ; i <= 3 ; i++) { Swap(cards, 0 , i); Dictionary<string, int> dict 1 = GenerateHelper(new int[] { cards[ 0 ] }); Dictionary<string, int> dict 2 = GenerateHelper(new int[] { cards[ 1 ], cards[ 2 ], cards[ 3 ] }); this.Construct(dict, dict 1 , dict 2 ); } for (int i = 0 ; i <= 3 ; i++) { for (int j = i + 1 ; j <= 3 ; j++) { Swap(cards, 0 , i); Swap(cards, 1 , j); Dictionary<string, int> dict 1 = GenerateHelper(new int[] { cards[ 0 ], cards[ 1 ] }); Dictionary<string, int> dict 2 = GenerateHelper(new int[] { cards[ 2 ], cards[ 3 ] }); this.Construct(dict, dict 1 , dict 2 ); } } } return dict; } private void Swap(int[] input, int i, int j) { int tmp = input[i]; input[i] = input[j]; input[j] = tmp; } private void Construct(Dictionary<string, int> dict, Dictionary<string, int> dict 1 , Dictionary<string, int> dict 2 ) { foreach (var kp 1 in dict 1 ) { foreach (var kp 2 in dict 2 ) { this.AddEntries(dict, kp 1 .Key, kp 2 .Key, kp 1 .Value, kp 2 .Value); } } } private void AddEntries(Dictionary<string, int> dict, string k 1 , string k 2 , int v 1 , int v 2 ) { if (!dict.ContainsKey( "(" + k 1 + "+" + k 2 + ")" )) { dict.Add( "(" + k 1 + "+" + k 2 + ")" , v 1 + v 2 ); } if (!dict.ContainsKey( "(" + k 1 + "-" + k 2 + ")" )) { dict.Add( "(" + k 1 + "-" + k 2 + ")" , v 1 - v 2 ); } if (!dict.ContainsKey( "(" + k 1 + "*" + k 2 + ")" )) { dict.Add( "(" + k 1 + "*" + k 2 + ")" , v 1 * v 2 ); } if ((v 2 != 0 ) && !dict.ContainsKey( "(" + k 1 + "/" + k 2 + ")" )) { dict.Add( "(" + k 1 + "/" + k 2 + ")" , v 1 / v 2 ); } } |
int oper(int i, int m, int n) { //枚举四种运算符
if(i == 1) return m + n;
if(i == 2) return m - n;
if(i == 3) return m * n;
if(n == 0 || m % n != 0) return INF;
else return m / n;
}
bool calcu1(int i, int j, int k) { //计算顺序1 ((a@b)@c)@d
int tmp1 = oper(i, a[0], a[1]);
int tmp2 = oper(j, tmp1, a[2]);
int tmp3 = oper(k, tmp2, a[3]);
if(tmp3 == 24 || tmp3 == -24) return true;
return false;
}
bool calcu2(int i, int j, int k) { //计算顺序2 (a@b)@(c@d)
int tmp1 = oper(i, a[0], a[1]);
int tmp2 = oper(k, a[2], a[3]);
int tmp3 = oper(j, tmp1, tmp2);
if(tmp3 == 24 || tmp3 == -24) return true;
return false;
}
sort(a, a+4);
do {
for(int i = 1; i <= 4; i++)
for(int j = 1; j <= 4; j++)
for(int k = 1; k <= 4; k++) {
if(calcu1(i, j, k) || calcu2(i, j, k)) flag = 1;
}
} while(next_permutation(a, a+4) && !flag);