【宽搜】The Clocks 时钟 (Usaco_Training 1.4)

The Clocks
IOI'94 - Day 2

Consider nine clocks arranged in a 3x3 array thusly:

|-------|    |-------|    |-------|    
|       |    |       |    |   |   |    
|---O   |    |---O   |    |   O   |          
|       |    |       |    |       |           
|-------|    |-------|    |-------|    
    A            B            C

|-------|    |-------|    |-------|
|       |    |       |    |       |
|   O   |    |   O   |    |   O   |
|   |   |    |   |   |    |   |   |
|-------|    |-------|    |-------|
    D            E            F

|-------|    |-------|    |-------|
|       |    |       |    |       |
|   O   |    |   O---|    |   O   |
|   |   |    |       |    |   |   |
|-------|    |-------|    |-------|
    G            H            I

The goal is to find a minimal sequence of moves to return all the dials to 12 o'clock. Nine different ways to turn the dials on the clocks are supplied via a table below; each way is called a move. Select for each move a number 1 through 9 which will cause the dials of the affected clocks (see next table) to be turned 90 degrees clockwise.

MoveAffected clocks1ABDE2ABC3BCEF4ADG5BDEFH6CFI7DEGH8GHI9EFHI
 
 

Example

Each number represents a time accoring to following table:

9 9 12       9 12 12       9 12 12        12 12 12      12 12 12 
6 6 6  5 ->  9  9  9  8->  9  9  9  4 ->  12  9  9  9-> 12 12 12 
6 3 6        6  6  6       9  9  9        12  9  9      12 12 12 

[But this might or might not be the `correct' answer; see below.]

PROGRAM NAME: clocks

INPUT FORMAT

Lines 1-3:Three lines of three space-separated numbers; each number represents the start time of one clock, 3, 6, 9, or 12. The ordering of the numbers corresponds to the first example above.

SAMPLE INPUT (file clocks.in)

9 9 12
6 6 6
6 3 6

OUTPUT FORMAT

A single line that contains a space separated list of the shortest sequence of moves (designated by numbers) which returns all the clocks to 12:00. If there is more than one solution, print the one which gives the lowest number when the moves are concatenated (e.g., 5 2 4 6 < 9 3 1 1).

SAMPLE OUTPUT (file clocks.out)

4 5 8 9

 

这一题很明显可以用宽搜解决(后来看别人的解题报告才知道深搜也可以)

宽搜的话,就需要队列维护,并且要记录方案,这里记录方案的时候理论上可以用string和数组记录,但是频繁使用string,程序就变得异常的慢!所以后来改成了数组记录,并且宽搜的空间是很宝贵的,所以记录方案的数组开合适就可以了,我开的50,如果100的话Usaco就会提示错误(还是英文的,看了好久才明白)

hash的设计可以用stl的set或者自己设计hash均可

当然,这一题宽搜是可以剪枝的!由于题目钟表的特殊性,不管哪个方案,用4次就相当于没用,所以当当前方案在到4次的时候就可以剪枝了

Usaco对格式很苛刻就不用说了,不能有多余空格,要有一个回车

C++ Code

/*
ID: jiangzh15
TASK: clocks
LANG: C++
http://oijzh.cnblogs.com
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<string>
#include<queue>
using namespace std;

const int kkk[]={1,1,4,16,64,256,1024,4096,16384,65536};//hash表中要用
const int ddd[10][10]={    //A B C D E F G H I
                          {0,0,0,0,0,0,0,0,0,0},
                          {0,1,1,0,1,1,0,0,0,0},//1        ABDE
                          {0,1,1,1,0,0,0,0,0,0},//2        ABC
                          {0,0,1,1,0,1,1,0,0,0},//3        BCEF
                          {0,1,0,0,1,0,0,1,0,0},//4        ADG
                          {0,0,1,0,1,1,1,0,1,0},//5        BDEFH
                          {0,0,0,1,0,0,1,0,0,1},//6        CFI
                          {0,0,0,0,1,1,0,1,1,0},//7        DEGH
                          {0,0,0,0,0,0,0,1,1,1},//8        GHI
                          {0,0,0,0,0,1,1,0,1,1},//9        EFHI
                      };
struct node{int a[10],step,c[50],way[10];};
queue<node> q;
node first;
bool h[262143+100];

int gethash(node x)
{
    int sum=0;
    for(int i=1;i<=9;i++)
        sum+=x.a[i]*kkk[i];
    return sum;
}

void check(node x)
{
    for(int i=1;i<=9;i++)
        if(x.a[i]!=0)return;
    for(int i=1;i<=x.step-1;i++) printf("%d ",x.c[i]);
    printf("%d\n",x.c[x.step]);
    exit(0);
}

int main()
{
    freopen("clocks.in","r",stdin);
    freopen("clocks.out","w",stdout);
    int i,j;
    for(i=1;i<=9;i++)
        {scanf("%d",&first.a[i]);first.a[i]=(first.a[i]%12)/3;}
    first.step=0;
    check(first);
    q.push(first);
    while(!q.empty())
    {
        node newnd,nd=q.front();q.pop();
        //printf("%d\n",nd.step);
        for(i=1;i<=9;i++)
        {
            if(nd.way[i]>=3)continue;
            newnd=nd;
            newnd.step++;
            newnd.way[i]++;
            for(j=1;j<=9;j++)
            {
                newnd.a[j]+=ddd[i][j];
                if(newnd.a[j]>=4)newnd.a[j]-=4;
            }
            newnd.c[newnd.step]=i;
            if(!h[gethash(newnd)])
            {
                /*printf("step=%d    ",newnd.step);
                for(int kk=1;kk<=newnd.step;kk++)
                    printf("%d ",newnd.c[kk]);
                printf("\n");*/
                check(newnd);
                h[gethash(newnd)]=true;
                q.push(newnd);
            }
        }
    }
    return 0;
}

 

 

转载于:https://www.cnblogs.com/oijzh/archive/2012/10/18/2729818.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值