hdu 1427 速算24点(java,DFS,全排列)
2017-03-27 18:19
337 查看
速算24点
[align=center]Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5070 Accepted Submission(s): 1310
[/align]
[align=left]Problem Description[/align]
速算24点相信绝大多数人都玩过。就是随机给你四张牌,包括A(1),2,3,4,5,6,7,8,9,10,J(11),Q(12),K(13)。要求只用'+','-','*','/'运算符以及括号改变运算顺序,使得最终运算结果为24(每个数必须且仅能用一次)。游戏很简单,但遇到无解的情况往往让人很郁闷。你的任务就是针对每一组随机产生的四张牌,判断是否有解。我们另外规定,整个计算过程中都不能出现小数。
[align=left]Input[/align]
每组输入数据占一行,给定四张牌。
[align=left]Output[/align]
每一组输入数据对应一行输出。如果有解则输出"Yes",无解则输出"No"。
[align=left]Sample Input[/align]
A 2 3 6
3 3 8 8
[align=left]Sample Output[/align]
Yes
No
[align=left]Author[/align]
LL
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1427
解题思路:之前没理解清楚题意,原来给定的牌不是按顺序的,牌的顺序可以打乱,因此要用到全排列来枚举四张牌的顺序。+,-,*,/和()运算用DFS来枚举,cur1代表前一个数或前一个运算结果,cur2代表后一个数或后一个运算结果,DFS分两种情况(@表示运算符):
(1)不加括号,按顺序:DFS(cur1@cur2,a[dex+1],dex+1); //计算完前两个数,再计算数组里的下一个数。
(2)后面的数加括号,即先运算后面的数cur1先放着:DFS(cur1,cur2+a[dex+1],dex+1); //先计算后两个数,把计算结果赋给cur2。
DFS的两种情况覆盖的情况有:(1)a @ b @ c @ d
(2)a @ ( b @ c ) @ d
(3)a @ ( b @ c @ d )
(4)a @ b @ ( c @ d )
还有一种情况 :a @ [ b @ ( c @ d ) ] 转换成了在全排列中的 b @ ( c @ d ) @ a。
在思考过程中想到,既然有全排列,那不加括号时会不会覆盖到所有情况呢?可以看出:
(2)a @ ( b @ c ) @ d 这个式子可以转变为 b @ c @ a @ d ;
(3)a @ ( b @ c @ d )这个式子可以转变为 b @ c @ d @ a ;
但是(4)a @ b @ ( c @ d )这个式子无法去掉括号,因此加括号的情况不能省略。
(以上的思路可能有些繁琐,直接暴力任取两个数字来枚举六个运算来计算也是可以的,时间都效率差不多。)
代码如下:
import java.util.*; public class Main { public static int[] a = new int[5]; public static boolean flog; public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNext()){ String str = sc.nextLine(); int cnt=0; for(int i=0;i<str.length();i++){ char c = str.charAt(i); if(i+1<str.length() && c=='1' && str.charAt(i+1)=='0'){ a[cnt++] = 10; }else if(c>='2' && c<='9'){ a[cnt++] = c-'0'; continue; } switch (c){ case 'A': a[cnt++] = 1;break; case 'J': a[cnt++] = 11;break; case 'Q': a[cnt++] = 12;break; case 'K': a[cnt++] = 13;break; } } flog = false; permutation(a,0,3); if(flog){ System.out.println("Yes"); }else{ System.out.println("No"); } } } public static void permutation(int[] num,int start,int end){ //写全排列 if(flog){ return; } if(start==end){ //每生成一次全排列,进行一次运算 DFS(a[0],a[1],1); return ; } for(int i=start;i<=end;i++){ //每次一个固定的数依次和后面的数交换位置 int temp = num[start]; num[start] = num[i]; num[i] = temp; permutation(num,start+1,end); //通过递归的每一层实现后面数字的全排列 temp = num[start]; //递归回来之后要恢复顺序,保证每次是两两交换,其他数字位置保持不变 num[start] = num[i]; num[i] = temp; } } public static void DFS(int cur1,int cur2,int dex){ //用DFS枚举计算 if(flog){ return; } if(dex == 3){ if(cur1+cur2==24 || cur1-cur2==24 || cur1*cur2==24 ){ flog = true ; }else if(cur2 !=0 && cur1%cur2==0 &&cur1/cur2==24){ flog = true; } return; } DFS(cur1+cur2,a[dex+1],dex+1); //没有括号的情况 DFS(cur1-cur2,a[dex+1],dex+1); //“-”“/”运算的结果和数字的前后顺序有关,因此都有两种情况 DFS(cur2-cur1,a[dex+1],dex+1); DFS(cur1*cur2,a[dex+1],dex+1); if(cur2!=0 && cur1%cur2 == 0 ){ //因为要保证除数不为0且除法运算后不出现小数 DFS(cur1/cur2,a[dex+1],dex+1); } if(cur1!=0 && cur2%cur1 == 0){ DFS(cur2/cur1,a[dex+1],dex+1); } DFS(cur1,cur2+a[dex+1],dex+1); //有括号的情况 DFS(cur1,cur2-a[dex+1],dex+1); DFS(cur1,a[dex+1]-cur2,dex+1); DFS(cur1,cur2*a[dex+1],dex+1); if(a[dex+1]!=0 && cur2%a[dex+1] == 0 ){ DFS(cur1,cur2/a[dex+1],dex+1); } if(cur2!=0 && a[dex+1]%cur2==0){ DFS(cur1,a[dex+1]/cur2,dex+1); } } }
相关文章推荐
- HDU-1716 排列2 (DFS)
- HDU 1716 排列 简单的DFS
- HDU 1427 速算24点(DFS) *
- 【HDU 1427 计算24点 DFS】
- 第七届 蓝桥杯决赛 Java B组 打靶 解题报告(DFS,回溯,全排列)
- hdu--1518--DFS(C&&java深搜之简单)
- HDU 1716排列2(dfs,可重集的排列,学习下去重以及格式)
- hdu 1427 速算24点 dfs暴力搜索
- HDU-1027(Ignatius and the Princess II)(全排列dfs())
- HDU 1427 dfs 速算24点
- hdu1261 java水过高精度排列组合。。
- Hdoj 1427 速算24点 【DFS】
- 【算法】求全排列 回溯 交换 DFS JAVA
- hdu 1427 24点暴力dfs
- hdu 1015 Safecracker【dfs 排列组合】
- hdu 1716 排列2 dfs 组合
- hdu 1716 排列2(全排列+dfs)
- hdu 1716 排列2(DFS搜索)
- hdu 1045 Fire Net (DFS java)
- HDU---1427(24点游戏,DFS回溯)