赞
踩
class Main { BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out)); Scanner s = new Scanner(System.in); // 一共要考虑的位置总数 int n; // 记录每一个位置的状态,0表示还没考虑到,1表示选它,2表示不选它 int[] st; public void run() throws IOException { n = s.nextInt(); st = new int[n + 1]; // 从第一个位置开始考虑 dfs(1); log.flush(); } // i 表示当前考虑到第几个位置了 private void dfs(int i) throws IOException { // 边界位置 if (i > n) { for (int k = 1; k <= n; k++) { if (st[k] == 1) { log.write(k + " "); } } log.write("\n"); return; } // 当前位置不选 st[i] = 2; // 考虑下一个位置 dfs(i + 1); // 回溯到父节点时恢复现场 st[i] = 0; // 当前位置要选 st[i] = 1; // 考虑下一个位置 dfs(i + 1); // 回溯到父节点时恢复现场 st[i] = 0; } public static void main(String[] args) throws IOException { new Main().run(); } }
第一层:1个节点执行一次for循环,O(n)
第二层:n个节点,每个节点都执行一次for循环,O(n*n)
第三层:n*(n-1)个节点,每个节点都执行一次for循环,O(n*(n-1)*n)
…
倒数第二层:n*(n-1)*(n-2)*… 2 个节点,同理,O(n*(n-1)*(n-2)* … *2*n)
最后一层:n!个节点,每个节点不用再执行一次for循环,但是需要输出数据,O(n!*n)
总复杂度: O ( ( n ∗ ( 1 + n ∗ ( n − 1 ) + n ∗ ( n − 1 ) ∗ ( n − 2 ) + . . . + n ! ) ) ) O((n*(1+n*(n-1)+n*(n-1)*(n-2)+...+n!))) O((n∗(1+n∗(n−1)+n∗(n−1)∗(n−2)+...+n!))),大概为 O ( n ∗ n ! ) O(n*n!) O(n∗n!)
class Main { BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out)); Scanner s = new Scanner(System.in); // 记录位置总数 int n; // 记录位置状态,0表示还为考虑该位置,1~n表示该位置上的取值 int[] state; // 记录对应数字是否使用过 boolean[] used; public void run() throws Exception { n = s.nextInt(); state = new int[n + 1]; used = new boolean[n + 1]; // 从第一个位置开始考虑 dfs(1); log.flush(); } public void dfs(int i) throws Exception { // 边界,即叶子节点的下一步,此时所有位置的取值已经考虑完毕 if (i > n) { for (int k = 1; k <= n; k++) { log.write(state[k] + " "); } log.write('\n'); return; } // 循环找到未使用过的最小数放到当前位置 (下一个节点的状态) for (int k = 1; k <= n; k++) { if (!used[k]) { // 在当前位置取值 state[i] = k; used[k] = true; // 考虑下一步取值 dfs(i + 1); // 回溯到父节点时恢复现场 state[i] = 0; used[k] = false; } } } public static void main(String[] args) throws Exception {new Main().run();} }
class Main { Scanner s = new Scanner(System.in); BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out)); // 记录n个空位 int n; // 记录m个需要选择的位置数量 int m; // 方案 int[] ways; // 当前位置最小能考虑到到数 int start = 1; public void run() throws IOException { n = s.nextInt(); m = s.nextInt(); ways = new int[m + 1]; dfs(1); log.flush(); } private void dfs(int i) throws IOException { // 剪枝:还未考虑到到的空位数量 > 待选的数的个数 (无效枚举) if (m - i + 1 > n - start + 1) { return; } // 边界 if (i > m) { // 扫描state for (int k = 1; k <= m; k++) { log.write(ways[k] + " "); } log.write('\n'); return; } for (int k = start; k <= n; k++) { ways[i] = k; start = k + 1; dfs(i + 1); // 恢复现场 ways[i] = 0; start = k; } } public static void main(String[] args) throws IOException {new Main().run(); } }
public class Main { Scanner s = new Scanner(System.in); // 输入数 int n; // 用来存全排列数 int[] nums; // 用来判断哪些数使用过 boolean[] used; int a, b, c; // 计数 int cnt; public void run() { n = s.nextInt(); nums = new int[10]; used = new boolean[10]; dfs(1); System.out.println(cnt); } public void dfs(int i) { // 边界 if (i > 9) { // 对每一种排列进行枚举分段 for (int x = 1; x <= 7; x++) { for (int y = x + 1; y <= 8; y++) { a = subNums(1, x); b = subNums(x + 1, y); c = subNums(y + 1, 9); // 对符合条件对数进行计数 if (n * c == a * c + b) cnt++; } } return; } // 全排列搜索模型 for (int k = 1; k <= 9; k++) { if (!used[k]) { nums[i] = k; used[k] = true; dfs(i + 1); nums[i] = 0; used[k] = false; } } } // 求每一段的数字 private int subNums(int l, int r) { int num = 0; for (int i = l; i <= r; i++) { num = num * 10 + nums[i]; } return num; } public static void main(String[] args) { new Main().run(); } }
class Main { BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out)); Scanner s = new Scanner(System.in); // 斐波那契的前n项 int n; // 递推式子 int[] f; public void run() throws Exception { n = s.nextInt(); f = new int[46]; // 初始化 f[1] = 0; f[2] = 1; // 从前到后递推 for (int i = 3; i <= n; i++) { f[i] = f[i - 1] + f[i - 2]; } for (int i = 1; i <= n; i++) { log.write(f[i] + " "); } log.flush(); } public static void main(String[] args) throws Exception {new Main().run();} }
import java.util.*; import java.io.*; class Main { Scanner s = new Scanner(System.in); // 矩阵数量 int n; // 输入的每一行 String line; // char数组 char[][] g; public void run() { n = s.nextInt(); g = new char[5][5]; while(n-- > 0) { // 填充数组 for (int i = 0; i < 5; i++) { line = s.next(); for (int j = 0; j < 5; j++) { g[i][j] = line.charAt(j); } } // 输出每次输入的g的ans minStep(g); } } public void minStep(char[][] c) { // 输入数组的替身 char[][] backup = new char[5][5]; for (int k = 0; k < 5; k++) { System.arraycopy(c[k], 0, backup[k], 0, 5); } int ans = 7; // 先枚举出第一行的所有操作情况 for (int op = 0; op < 32; op++) { // 每次op让step归0 int step = 0; // 二进制数中对数字为1的位置进行翻转 for (int i = 0; i < 5; i++) { if ((op >> i & 1) == 1) { turn(backup, 0, i); step++; } } // 从第一行到第四行开始扫描 for (int i = 0; i < 4; i++) { for (int j = 0; j < 5; j++) { // 如果当前行的当前列元素为0则对下一行对应位置进行翻转 if (backup[i][j] == '0') { turn(backup, i + 1, j); step++; } } } boolean bright = true; // 扫描最后一行元素,判断其是否全为1 for (int i = 0; i < 5; i++) { if(backup[4][i] != '1') { bright = false; } } // 如果最后一行全亮,则本次op有效,与前一次的移动步数比较,以至于所有op结束后找到最小值 if (bright) { ans = Math.min(ans, step); } // 恢复替身改变之前的状态 for (int k = 0; k < 5; k++) { System.arraycopy(c[k], 0, backup[k], 0, 5); } } // 判断最小步数是否大于6,如果大于6则返回-1 if(ans > 6) ans = -1; System.out.println(ans); } // 关于(x, y)的5个点偏移量 int[] dx = {-1, 0, 1, 0, 0}; int[] dy = {0, 1, 0, -1, 0}; public void turn(char[][] c, int x, int y) { for (int i = 0; i < 5; i++) { // (a, b)为(x, y)附加对应偏移量的点 int a = x + dx[i]; int b = y + dy[i]; // 判断一下边界,如果越界,这该点无效,不需要翻转 if (a < 0 || a >=5 || b < 0 || b >= 5) continue; // 对该点进行翻转 c[a][b] = c[a][b] == '1' ? '0' : '1'; } } public static void main(String[] args) {new Main().run();} }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。