《DFS》北京2008的挂钟

E.北京2008的挂钟

时间限制 1000 ms
内存限制 128 MB

题目描述
在这里插入图片描述

在2008北京奥运会雄伟的主会场的墙上,挂着如上图所示的3*3的九个挂钟(一开始指针即时针指向的位置请根据输入数据调整)。然而此次奥运会给与了大家一个机会,去用最少的移动操作改变上面的挂钟的时间全部为12点正(我们只考虑时针)。然而每一次操作并不是任意的,我们必须按照下面给出的列表对于挂钟进行改变。每一次操作我们给而且必须给指定的操作挂钟进行,每一个挂钟顺时针转动90度。列表如下:
   操作   指定的操作挂钟
   1     ABDE
   2     ABC
   3     BCEF
   4     ADG
   5     BDEFH
   6     CFI
   7     DEGH
   8     GHI
   9     EFHI

输入数据

你的程序按照标准的 3∗3 格式读入,一共 9 个 0−3 的数。 0 代表 12 点 ,1 代表 3 点 ,2 代表 6 点 ,3 代表 9 点。
Your program is to read from standard input. Nine numbers give the start positions of the dials. 0=12 o’clock, 1=3 o’clock, 2=6 o’clock, 3=9 o’clock.

输出数据

你的程序需要写出标准的输出。输出一个最短的能够使所有挂钟指向 12 点的移动操作序列,中间以空格隔开,最后有空格,加回车。这一条最短操作需要是所有最短操作中最小的,也就是说选择最小的第一个操作数,如果第一个操作数相等,那么选择最小的第二个操作数……以此类推。值得肯定的是,这一条操作序列是唯一的。
Your program is to write to standard output. Output a shortest sorted sequence of moves (numbers), which returns all the dials to 12 o’clock. You are convinced that the answer is unique.

样例输入

3 3 0
2 2 2
2 1 2

样例输出

4 5 8 9

思路解析:

共有九种操作,因为只有四个状态,所以每种操作只需要执行0到3次就可以覆盖所有情况。(剪枝)

对所有的操作进行搜索,可能情况4^9 即2^18种情况,可以暴力。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#define INF 0x7FFFFFFF //int 最大值
#define maxSize 9
using namespace std;

int clock1[maxSize+5];//时钟状态。clock1是为了防止出现变异错误,clock有内部定义
int changeTime[maxSize+5];//每个操作使用的次数
bool isOk=false;

int op[maxSize][maxSize]={
{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}
};

void dfs(int n)//dfs每个操作
{
    if(n==9)
    {
        isOk=true;
        for(int i=0;i<9;i++)//对于每一个钟表进行遍历。
        {
            if(clock1[i]%4!=0)
            {
                isOk=false;
                break;
            }
        }
        return ;
    }

    for(int i=0;i<=3;i++)//因为时钟只有四个状态,每个操作所以只要转 0,1,2,3次就可以达到所有状态。
    {
        changeTime[n]=i;
        for(int j=0;j<9;j++)//每个clock都要进行操作。
            clock1[j]+=i*op[n][j];

        dfs(n+1);
        if(isOk)
            return ;

        for(int j=0;j<9;j++)//回溯。
            clock1[j]-=i*op[n][j];
    }
}

int main()
{
    for(int i=0;i<9;i++)
        cin>>clock1[i];

    memset(changeTime,0,sizeof(changeTime));
    isOk=false;
    dfs(0);

    for(int i=0;i<9;i++)//对于每个操作
        for(int j=0;j<changeTime[i];j++)//依字典序输出其操作
            cout<<i+1<<" ";
    cout<<endl;

    return 0;
}

提示一点:

题目说要字典序输出,我们进行的操作刚好满足,就不再进一步排序了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值