1166:The Clocks

代码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枚举+剪枝

  1. 每次拨动指针转90度,那么有效的拨动数只能是0、1、2、3。比如又再拨动一次就会重复拨动0次的效果。
  2. 一个移动方案有4种不同的拨动方式,一共有9个移动方案,那么可能的解就有4^9个。
  3. 此题只要求我们求最小移动的次数,那么在枚举的过程中,如果发现当前枚举的情况已超过最小移动次数,可以剪枝。
    参考: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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值