请你计算,一共有多少种不同的剪取方法。
我做这道题就用了两个回溯(思路有点复杂)。。看来回溯对于蓝桥杯很吃香啊。
1.首先用回溯从12个数里面找到5个数
2.每找到5个数把vist数组清0,并且把5个数的坐标分别写入vist数组中
3.然后对vist数组进行回溯,看看从起点开始能不能走完5个数。可以就++否则继续找别的5个数
对回溯不太了解的话可以先试着解决八皇后问题,很经典的题目
总体代码需要改进还有很多
#include<iostream>using namespace std;int a[3][4] = { 0 };int v[13] = { 0 };int vist[3][4] = { 0 };int S = 0;int fz = 0;int q[3][4];int pd2(int i, int j){ if (i < 0 || j < 0 || i >= 3 || j >= 4 || a[i][j] == 0) return 0; return 1;}int pd3(int v[3][4]){ for (int i = 0; i < 3; i++){ for (int j = 0; j < 4; j++) { if (a[i][j] != 0){ if (v[i][j] == 0) return 0; } } } return 1;}void dfs(int i, int j){ if (pd3(vist)){//如果5个数对应的都为1,就满足 fz = 1; return; } else{ if (vist[i][j] == 0){//经过判断能到达的坐标都赋值为1 vist[i][j] = 1; if (pd2(i + 1, j)) dfs(i + 1, j); if (pd2(i - 1, j)) dfs(i - 1, j); if (pd2(i, j - 1)) dfs(i, j - 1); if (pd2(i, j + 1)) dfs(i, j + 1); } }}void f(int i, int j, int sum, int n){//寻找5个数的回溯方法 if (sum == 5){//找到5个数 int q1, q2; for (int i = 0; i < 3; i++){ for (int j = 0; j < 4; j++) if (a[i][j] != 0){//把第一个数的坐标记录下来,做为下一个回溯的起点 q1 = i; q2 = j; break; } } for (int i = 0; i < 3; i++) for (int j = 0; j < 4; j++) vist[i][j] = 0;//每次vist清0 dfs(q1, q2); if (fz == 1){ S++; fz = 0; } } else{//进行回溯找到5个数 for (int k = n; k <= 12; k++){ if (v[k] == 0) { v[k] = 1; int q1, q2; for (int i = 0; i < 3; i++){//这点和乒乓球安排日程和方格填数就不一样了 for (int j = 0; j < 4; j++) if (q[i][j] == k){//他不是像八皇后一样每个位置的数都会变,他有固定的数,所以要把那个数对应的坐标记录下来 q1 = i; q2 = j; } } a[q1][q2] = k; if (q2 == 3)//这点注意换行 f(q1 + 1, 0, sum + 1, k + 1); else f(q1, q2 + 1, sum + 1, k + 1); a[q1][q2] = 0; v[k] = 0; } } }}int main(){ int k = 0; for (int i = 0; i < 3; i++){ for (int j = 0; j < 4; j++) q[i][j] = ++k; }//先对数组赋值 f(0, 0, 0, 1); PRintf("%d", S); return 0;}代码能改进的地方很多,希望大家指出。一起交流嘛
新闻热点
疑难解答