代码1:纯枚举
不需要单独判断最小方案;
参考:https://blog.csdn.net/Ericipher/article/details/79661439
#include <iostream>
#include <cstring>
using namespace std;
int arr[10], num[10];
void Print(int n,int x) {
for (int j = 1; j <= n; j++)
printf("%d ", x);
}
int main() {
int i, i1, i2, i3, i4, i5, i6, i7, i8, i9;
for (i = 0; i < 9; i++)
cin >> arr[i];
for(i1=0;i1<4;i1++)//第i种方案使用了i1次
for (i2 = 0; i2 < 4; i2++)
for (i3 = 0; i3 < 4; i3++)
for (i4 = 0; i4 < 4; i4++)
for (i5 = 0; i5 < 4; i5++)
for (i6 = 0; i6 < 4; i6++)
for (i7 = 0; i7 < 4; i7++)
for (i8 = 0; i8 < 4; i8++)
for (i9 = 0; i9 < 4; i9++) {
num[0] = (arr[0] + i1 + i2 + i4) % 4;
num[1] = (arr[1] + i1 + i2 + i3 + i5) % 4;
num[2] = (arr[2] + i2 + i3 + i6) % 4;
num[3] = (arr[3] + i1 + i4 + i5 + i7) % 4;
num[4] = (arr[4] + i1 + i3 + i5 + i7 + i9) % 4;
num[5] = (arr[5] + i3 + i5 + i6 + i9) % 4;
num[6] = (arr[6] + i4 + i7 + i8) % 4;
num[7] = (arr[7] + i5 + i7 + i8 + i9) % 4;
num[8] = (arr[8] + i6 + i8 + i9) % 4;
int sum = 0;
for (i = 0; i < 9; i++)
sum += num[i];
if (sum == 0) {//每个时钟都归位
Print(i1, 1);
Print(i2, 2);
Print(i3, 3);
Print(i4, 4);
Print(i5, 5);
Print(i6, 6);
Print(i7, 7);
Print(i8, 8);
Print(i9, 9);
return 0;
}
}
}
代码2:枚举+剪枝
- 每次拨动指针转90度,那么有效的拨动数只能是0、1、2、3。比如又再拨动一次就会重复拨动0次的效果。
- 一个移动方案有4种不同的拨动方式,一共有9个移动方案,那么可能的解就有4^9个。
- 此题只要求我们求最小移动的次数,那么在枚举的过程中,如果发现当前枚举的情况已超过最小移动次数,可以剪枝。
参考:https://blog.csdn.net/tp7309/article/details/53027077
AC代码:
//枚举+剪枝
#include <iostream>
#include <cstring>
using namespace std;
const int N = 9;
int cases[N][N] = {
{1, 1, 0, 1, 1, 0, 0, 0, 0},
{1, 1, 1, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 0, 1, 1, 0, 0, 0},
{1, 0, 0, 1, 0, 0, 1, 0, 0},
{0, 1, 0, 1, 1, 1, 0, 1, 0},
{0, 0, 1, 0, 0, 1, 0, 0, 1},
{0, 0, 0, 1, 1, 0, 1, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 1, 1},
{0, 0, 0, 0, 1, 1, 0, 1, 1} };
int arr[N];
int minCount = 4 * N + 1;//每个时钟拨4次,一定可以归位
int res[N];
//count:存储本次递归各方案使用次数 ,num: 本次采取第num种方案;curCount: 目前一共走了几步;
void calc(int(&count)[N], int num, int curCount) {
if (curCount > minCount)//当前次数>minCount,剪枝
return;
if (num == N) {//递归出口
int j;
for (j = 0; j < N; j++) {//第j个时钟是否归位
int sum = arr[j];
for (int k = 0; k < N; k++) {//每种方案
sum += count[k] * cases[k][j];
}
if (sum % 4 != 0)//没有归位
break;
}
if (j == N) {//所有时钟归位
if (curCount < minCount) {
minCount = curCount;
memcpy(res, count, sizeof(count));//更新结果
}
}
return;
}
int nextNum = num + 1;
for (count[num] = 0; count[num] < 4; count[num]++)//第num种方案采取count[num]次
calc(count, nextNum, curCount + count[num]);//递归
}
int main() {
memset(res, 0, sizeof(res));
bool flag = true;
for (int i = 0; i < N; i++) {
cin >> arr[i];
if (arr[i] % 4 != 0)
flag = false;
}
if (flag)//一开始所有时钟都归位
return 0;
int count[N];//存储采取0-8每种方案的次数
calc(count, 0, 0);//从第0方案到第8方案,遍历
for (int i = 0; i < N; i++) {
for (int j = 0; j < res[i]; j++)
cout << i + 1 << " ";
}
return 0;
}