简单型枚举
「42 点问题」
题目描述
请你设计一个程序对该问题进行解答。
众所周知在扑克牌中,有一个老掉牙的游戏叫做 24 点,选取 4 张牌进行加减乘除,看是否能得出 24 这个答案。
现在小蓝同学发明了一个新游戏,他从扑克牌中依次抽出6张牌,注意不是一次抽出,进行计算,看是否能够组成 42 点,满足输出 YES,反之输出 NO。
最先抽出来的牌作为第一个操作数,抽出牌做第二个操作数,运算结果再当作第一个操作数,继续进行操作。
注:除不尽的情况保留整数,而且扑克牌的四张 1010 都丢了,不会出现 10。
请设计一个程序对该问题进行解答。
输入描述
输出仅一行包含 6 个字符。
保证字符 ∈ 3 4 5 6 7 8 9 10 J Q K A 2。
输出描述
若给出到字符能够组成 4242 点 , 满足输出 YES,反之输出 NO。
输入输出样例
示例
输入
K A Q 6 2 3
输出
YES
样例说明
K×A=K 即 13×1=13
13/12=1保留整数
1+6=7
7∗2=14
14∗3=42
运行限制
最大运行时间:1s
最大运行内存: 128M
备注:
相当于有一个大数组,大数组里面有6个小数组
第一个小数组里只有num[0]
第二个小数组里有num[0]分别加减乘除num[1]后的4个结果
第三个小数组里有第二个小数组里的4个数分别对num[2]进行加减乘除后的结果,也就是4个数*4个运算=16个结果
...
以此类推
最后遍历最后一个,也就是第六个小数组,里面如果有42就YES,没有就NO
代码
import java.util.Scanner;
import java.util.Vector;
public class Main {
static Vector<Vector<Integer>> ans=new Vector<Vector<Integer>>();
static int[] num=new int[6];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 6; i++) {
String s=sc.next();
if(Character.isDigit(s.charAt(0))) {
num[i]=s.charAt(0)-'0';
}else {
if(s.equals("J")) {
num[i]=11;
}else if(s.equals("Q")) {
num[i]=12;
}else if(s.equals("K")) {
num[i]=13;
}else if(s.equals("A")) {
num[i]=1;
}
}
}
ans.add(new Vector<>());
ans.get(0).add(num[0]);
for (int i = 0; i < 5; i++) {
ans.add(new Vector<>());
for (int j = 0; j < ans.get(i).size(); j++) {
int t=ans.get(i).get(j);
ans.get(i+1).add(t+num[i+1]);
ans.get(i+1).add(t-num[i+1]);
ans.get(i+1).add(t*num[i+1]);
ans.get(i+1).add(t/num[i+1]);
}
}
boolean flag=false;
for (int i = 0; i < ans.get(5).size(); i++) {
if(ans.get(5).get(i)==42) {
flag=true;
break;
}
}
if(flag) {
System.out.println("YES");
}else {
System.out.println("NO");
}
}
}
组合型枚举
组合型模板
注意:
1.chosen.remove((Object)x);
vector的remove有两种,一种是传入index,一种是传入要删除的东西;这里的东西刚好是int类型,就会被理解为是index,就会出错,所以一定要加(Object)
2.这段代码,两种写法都可以
2.1:这种写法,输出的答案特点是:1 2 ;1 3;2 3
calc(x + 1);
chosen.addElement(x);
calc(x + 1);
chosen.remove((Object)x);
2.2:这种写法,输出的答案特点是:2 3;1 3;1 2
chosen.addElement(x);
calc(x + 1);
chosen.remove((Object)x);
calc(x + 1);
public class Main {
static int n;
static int m;//选m个数
static Vector<Integer> chosen = new Vector<Integer>();
static <object> void calc(int x) {
if (chosen.size() > m || chosen.size() + (n - x + 1) < m) //剪枝
return;
if (x == n + 1) { //选够了m个数输出
String ansTem = "";
for (int i = 0; i < chosen.size(); i++)
System.out.print(chosen.get(i)+" ");
System.out.println("");
return;
}
calc(x + 1);
chosen.addElement(x);
calc(x + 1);
chosen.remove((Object)x);//注意
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
m = in.nextInt();
calc(1);
}
}
「公平抽签」
题目描述
小A的学校,蓝桥杯的参赛名额非常有限,只有 m 个名额,但是共有 n 个人报名。
作为老师非常苦恼,他不知道该让谁去,他在寻求一个绝对公平的方式。
于是他准备让大家抽签决定,即 m 个签是去,剩下的是不去。
小A非常想弄明白最后的抽签结果会有多少种不同到情况,请你设计一个程序帮帮小A!
输入描述
输入第一行包含两个字符n,m,其含义如题所述。
接下来第二行到第 n+1 行每行包含一个字符串 S ,表示个人名。
1≤m≤n≤15。
输出描述
输出共若干行,每行包含 m 个字符串,表示该结果被选中到人名。
输入输出样例
示例
输入
3 2
xiaowang
xiaoA
xiaoli
输出
xiaowang xiaoA
xiaowang xiaoli
xiaoA xiaoli
运行限制
最大运行时间:1s
最大运行内存: 128M
代码
import java.util.Scanner;
import java.util.Vector;
public class Main {
static int n;
static int m;
static Vector<Integer> chosen=new Vector<Integer>();
static Vector<String> name=new Vector<String>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n=sc.nextInt();
m=sc.nextInt();
for (int i= 0; i < n; i++) {
name.add(sc.next());
}
calc(1);
}
private static void calc(int i) {
if(chosen.size()>m||chosen.size()+(n-i+1)<m)return;
if(i==n+1) {
for (Integer x : chosen) {
System.out.print(name.get(x-1)+" ");
}
System.out.println();
}
chosen.add(i);
calc(i+1);
chosen.remove((Object)i);
calc(i+1);
}
}
排列型枚举
全排列模板1
static int n;
static int[] order =new int[20];
static boolean[] chosen =new boolean[20];
static <object> void calc(int x) {
if (x == n + 1) { //选够了m个数输出
String ansTem = "";
for (int i = 1; i <=n ; i++)
System.out.println(order[i]);
return;
}
for (int i = 1; i <= n; i++) {
if (chosen[i]) continue;
order[x] = i;
chosen[i] =true;
calc(x + 1);
chosen[i] = false;
order[x] = 0;
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
for (int i = 0; i < n; i++) {
String s;
s=in.next();
name.addElement(s);
}
calc(1);
}
全排列模板2
这个好记点
public class A09_全排列 { //——整数数组
// 数字型、字符串、含重复元素的全排列 子集的生成、真子集、集合
public static void main(String[] args) {
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
f(arr1, 0);
}
// 确认某一个排列的第k位
private static void f(int[] arr, int k) {
if (k == arr.length) { // 全部确认
for (int x : arr) {
System.out.print(x);
}
System.out.println();
return;
}
for (int i = k; i < arr.length; i++) { // 选定第k位,
// 将第i位和第k位交换
int t = arr[i];arr[i] = arr[k];arr[k] = t;
f(arr, k + 1); // 移交下一层去确认k+1位
// 回溯(换回来)
t = arr[i];arr[i] = arr[k];arr[k] = t;
}
}
}
「座次问题」
题目描述
小A 的学校,老师好不容易解决了蓝桥杯的报名问题,现在老师又犯愁了。
现在有 N 位同学参加比赛,但是老师想给他们排座位,但是排列方式太多了。
老师非常想弄明白最后的排座次的结果是什么样子的,到底有多少种结果。
请设计一个程序帮助老师。
最后输出各种情况的人名即可,一行一种情况,每种情况的名字按照报名即输入顺序排序。
输入描述
输入第一行包含一个整数 N。
接下来 N 行每行包含一个字符串Si表示人名。
1≤N≤10
输出描述
输出共若干行,每行输出各种情况的人名。一行一种情况,每种情况的名字按照报名即输入顺序排序。
输入输出样例
示例
输入
3
xiaowang
xiaoA
xiaoli
输出
xiaowang xiaoA xiaoli
xiaowang xiaoli xiaoA
xiaoA xiaowang xiaoli
xiaoA xiaoli xiaowang
xiaoli xiaowang xiaoA
xiaoli xiaoA xiaowang
运行限制
最大运行时间:1s
最大运行内存: 128M
代码
import java.util.Scanner;
import java.util.Vector;
public class Main {
static int n;
static Vector<String> name = new Vector<String>();
static int[] order =new int[20];
static boolean[] chosen =new boolean[20];
static <object> void calc(int x) {
if (x == n + 1) { //选够了m个数输出
String ansTem = "";
for (int i = 1; i <=n ; i++)
ansTem += name.get(order[i]-1) + " ";
System.out.println(ansTem);
return;
}
for (int i = 1; i <= n; i++) {
if (chosen[i]) continue;
order[x] = i;
chosen[i] =true;
calc(x + 1);
chosen[i] = false;
order[x] = 0;
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
n = in.nextInt();
for (int i = 0; i < n; i++) {
String s;
s=in.next();
name.addElement(s);
}
calc(1);
}
}