1. 输入描述
总共有36张牌,每张牌是1-9。每个数字4张牌。输入只有一行,包含13个代表着13张牌的数字,用空格分隔,每个数字在1~9之间,数据保证同种数字最多出现4次。
2. 输出描述
输出同样是一行,包含1个或以上的数字。代表他再取到哪些牌可以和牌。若满足条件的有多种牌,请按从小到大的顺序输出。若没有满足条件的牌,请输出一个数字0,其中和牌的条件如下:
- 14张牌中有2张相同数字的牌,称为雀头。
- 除去上述2张牌,剩下12张牌可以组成4个顺子或刻子。顺子的意思是递增的连续3个数字牌(例如234,567等),刻子的意思是相同数字的3个数字牌(例如111,777)
3. 思路描述
从1到9九个数字进行遍历,判断当前已有的十三张牌中当前数字的牌是否已有四张,若没有则加入并且判断是否能满足条件,和了就将当前数字加入最终答案中并尝试下一个数字,若当前数字已有四张则跳过并尝试下一个数字。
而判断是否能满足条件的方法通过回溯法来实现,思路如下图:
4. 代码实现
import java.util.Scanner;
public class Main{
private static boolean pass(boolean hadHeader,int count,int[] poker){
if(count==0){
return true;
}
if(hadHeader){
for(int i=0;i<9;i++){
if(poker[i]>2){
poker[i]-=3;
if(pass(true,count-3,poker)){
return true;
}
poker[i]+=3;
}
if(i<7&&poker[i]>0&&poker[i+1]>0&&poker[i+2]>0){
poker[i]--;
poker[i+1]--;
poker[i+2]--;
if(pass(true,count-3,poker)){
return true;
}
poker[i]++;
poker[i+1]++;
poker[i+2]++;
}
}
return false;
}else{
for(int i=0;i<9;i++){
if(poker[i]>1){
poker[i]-=2;
if(pass(true,count-2,poker)){
return true;
}
poker[i]+=2;
}
}
return false;
}
}
private static void copyArray(int[] arrayA,int[] arrayB){
for(int i=0;i<9;i++){
arrayA[i]=arrayB[i];
}
}
public static void main(String[] args){
/*
* enter data to int array poker
*/
StringBuffer result=new StringBuffer();
Scanner scan=new Scanner(System.in);
String[] temp=scan.nextLine().split(" ");
int[] poker=new int[9],pokerBackup=new int[9];
for(int i=0;i<13;i++){
poker[Integer.parseInt(temp[i])-1]++;
}
for(int i=0;i<9;i++){
copyArray(pokerBackup,poker);
if(poker[i]<4){
poker[i]++;
if(pass(false,14,poker)){
if(result.length()!=0){
result.append(" ");
}
result.append(String.valueOf(i+1));
}
poker[i]--;
}
copyArray(poker,pokerBackup);
}
if(result.length()==0){
System.out.println("0");
}else{
System.out.println(result.toString());
}
}
}