目录
- 专栏导读
- 一、题目描述
- 二、输入描述
- 三、输出描述
- 1、输入
- 2、输出
- 3、说明
- 四、解题思路
- 1、题目解读
- 2、具体步骤
- 五、Java算法源码
- 六、效果展示
- 1、输入
- 2、输出
- 3、说明
华为OD机试 2023B卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷)》。
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
有这么一款单人卡牌游戏,牌面由颜色和数字组成,颜色为红、黄、蓝、绿中的一种,数字为0-9中的一个。游戏开始时玩家从手牌中选取一张卡牌打出,接下来如果玩家手中有和他上一次打出的手牌颜色或者数字相同的手牌,他可以继续将该手牌打出,直至手牌打光或者没有符合条件可以继续打出的手牌。
现给定一副手牌,请找到最优的出牌策略,使打出的手牌最多。
二、输入描述
输入为两行,第一行是每张手牌的数字,数字由空格分隔,第二张为对应的每张手牌的颜色,用rybg这4个字母分别代表4种颜色,字母也由空格分隔。手牌数量不超过10。
三、输出描述
输出一个数字,即最多能打出的手牌的数量。
1、输入
1 4 3 4 5
r y b b r
2、输出
3
3、说明
- 如果打1r,5r,则打出两张
- 如果打4y,4b,3b,则打出三张
四、解题思路
1、题目解读
从手牌中选取一张卡牌打出,接下来如果玩家手中有和他上一次打出的手牌颜色或者数字相同的手牌,他可以继续将该手牌打出,直至手牌打光或者没有符合条件可以继续打出的手牌。
现给定一副手牌,请找到最优的出牌策略,使打出的手牌最多
2、具体步骤
- 第一行输入每张手牌的数字numArr;
- 第二行输入每张手牌的颜色colorArr;
- 定义集合jokerList,将数字和颜色配对,组成joker;
- 遍历扑克牌jokerList;
- 通过深度优先搜索dfs算法获取最优的出牌策略,使打出的手牌最多;
- 当没有牌或者剩余的牌都已经搜索完毕时,退出搜索;
- 获取下一张扑克牌next;
- 如果可以打出(玩家手中有和他上一次打出的手牌颜色或者数字相同的手牌);
- 将next追加到builder;
- 并从jokerList中移除next;
- 重置当前的扑克牌joker为next;
- 连续打出的手牌step+1;
- 下一张扑克牌坐标归零;
- 再次调用dfs,循环往复,获取可以打出的最多手牌;
- 输出可以打出的最多手牌maxStep;
五、Java算法源码
public class OdTest03 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 每张手牌的数字
String[] numArr = sc.nextLine().split(" ");
// 每张手牌的颜色
String[] colorArr = sc.nextLine().split(" ");
// 将数字和颜色配对,组成joker
List<String> jokerList = new ArrayList<String>();
for (int i = 0; i < numArr.length; i++) {
jokerList.add(numArr[i] + colorArr[i]);
}
int maxStep = 0;
for (int i = 0; i < jokerList.size(); i++) {
String joker = jokerList.get(i);
List<String> tempList = new ArrayList<String>(jokerList);
StringBuilder builder = new StringBuilder();
builder.append(joker).append(" ");
tempList.remove(joker);
// 通过深度优先搜索dfs算法获取最优的出牌策略,使打出的手牌最多
int step = def(joker, tempList, 0, 1, builder);
System.out.println(builder + " ---> 连续打出的手牌数量=" + step);
builder = new StringBuilder();
// 获取可以打出的最多手牌
if (step > maxStep) {
maxStep = step;
}
}
System.out.println(maxStep);
}
/**
* 通过深度优先搜索dfs算法获取最优的出牌策略,使打出的手牌最多
*
* @param joker 当前的扑克牌
* @param jokerList 剩下的扑克牌
* @param i 下一张扑克牌坐标
* @param step 连续打出的手牌数量
* @param builder 为了便于分析,将连续打出的扑克牌拼接到一起
* @return
*/
public static int def(String joker, List<String> jokerList, int i, int step, StringBuilder builder) {
// 当没有牌或者剩余的牌都已经搜索完毕时,退出搜索
if (jokerList.size() == 0 || i == jokerList.size()) {
return step;
}
String next = "";
// 获取下一张扑克牌
next = jokerList.get(i);
i++;
// 是否可以打出
if (isSame(joker, next)) {
builder.append(next).append(" ");
jokerList.remove(next);
// 重置当前的扑克牌
joker = next;
// 连续打出的手牌+1
step++;
// 下一张扑克牌坐标归零
i = 0;
}
return def(joker, jokerList, i, step, builder);
}
/**
* 是否可以打出(玩家手中有和他上一次打出的手牌颜色或者数字相同的手牌)
* @param joker
* @param next
* @return
*/
private static boolean isSame(String joker, String next) {
for (int i = 0; i < joker.length(); i++) {
String numOrColor = joker.charAt(i) + "";
if (next.contains(numOrColor)) {
return true;
}
}
return false;
}
}
六、效果展示
1、输入
1 4 3 4 5 6 6
r y b b r g y
2、输出
5
3、说明
1r 5r —> 连续打出的手牌数量=2
4y 4b 3b —> 连续打出的手牌数量=3
3b 4b 4y 6y 6g —> 连续打出的手牌数量=5
4b 4y 6y 6g —> 连续打出的手牌数量=4
5r 1r —> 连续打出的手牌数量=2
6g 6y 4y 4b 3b —> 连续打出的手牌数量=5
6y 4y 4b 3b —> 连续打出的手牌数量=4
🏆下一篇:华为OD机试 - 最长的顺子 - 感谢@禁止你发言提供的更简便算法(Java 2023 B卷 200分)
🏆本文收录于,华为OD机试(JAVA)真题(A卷+B卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。