正文

USACO Section 1.4 The Clocks2007-04-10 21:58:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/cruxd/24776.html

分享到:

老实的说,这该称之为穷举——但搜索不也是把所有可能的情况列出来么?无非用的方法巧妙一点……额,是巧妙的多罢了。传说中有位俊朗的数学家王子,为了得到邻国数学家公主的一片芳心,发动全国之力,每个人验证一个数是否为质数,从而得到了一个相当大的质数,为古巴比伦数学的蓬勃发展作出了不可磨灭的贡献。——这就是穷举。BTW,他的想法和并行计算机如出一辙,也不知道谁从谁哪里得到的灵感。

但是我听说,两个数学家走到一起,下场都是很悲惨的,不是女孩把拖鞋下到锅里就是男孩饿死。但似乎王子和公主们不用担心这些……

扯远了。这道题本来想写华丽的bfs……但是写的太华丽了,调试到最后连自己都不知道在写什么。题意是这样的,有9个时钟(A到I),每个时钟只有4档可以拨,12点,3点,6点,9点。有9种操作,每种操作把其中的某几个时钟顺时针拨一档。

Move Affected clocks
1 ABDE
2 ABC
3 BCEF
4 ADG
5 BDEFH
6 CFI
7 DEGH
8 GHI
9 EFHI

那么,给出一个时钟的排列法,如

9 9 12
6 6 6
6 3 6

求,最小需要几步,把所有时钟都挑到12点?

这是一个非常好的bfs和dfs练习题,但是也相当的难写。在看了某牛人的dfs代码之后,我发现自己比看过之前懂的更少。胡Core也教导我们,要以艰苦朴素为荣。综上所述,我采用了穷举的方法。

但是这也是有前提的。第一,每一个时钟都只有四种状态。换句话说,每种操作也是四种状态,进行0,1,2,3次。第二,4的9次方不大……

/*
ID: Crux.D
PROG: clocks
LANG: C++
*/

#include <cstdio>
#include <string>
#include <cstdlib>

const int L = 10000;

FILE * fin = fopen ( "clocks.in", "r" );
FILE * fout = fopen ( "clocks.out", "w" );

int x[9];

int c[9][9] = {
{ 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 }
}, a[9];

bool res ()
{
    int i;
    int r[9] =
    {
        0, 0, 0, 1, 1, 0, 0, 1, 1
    };
    for ( i = 0; i < 9; i ++ )
    {
        if ( x[i] != r[i] )
        {
            return false;
        }
    }
    return true;
}

bool check ()
{
    int i, k, t[9];
    memcpy ( t, a, sizeof ( t ) );
    for ( i = 0; i < 9; i ++ )
    {
        for ( k = 0; k < 9; k ++ )
        {
            t[k] += c[i][k] * x[i];
        }
    }
    /*
    if ( res () )
    {
        for ( i = 0; i < 9; i ++ )
        {
            printf ( "%d ", t[i] );
        }
        printf ( "\n" );
    }
    */
    for ( i = 0; i < 9; i ++ )
    {
        if ( t[i] % 4 != 0 )
        {
            return false;
        }
    }
    return true;
}

void print ()
{
    int i, k, ct = 0;
    for ( i = 0; i < 9; i ++ )
    {
        for ( k = 0; k < x[i]; k ++ )
        {
            if ( ct ++ )
            {
                fprintf ( fout, " " );
            }
            fprintf ( fout, "%d", i + 1 );
        }
    }
    fprintf ( fout, "\n" );
}

void init ()
{
    int i, t;
    for ( i = 0; i < 9; i ++ )
    {
        fscanf ( fin, "%d", &t );
        a[i] = t / 3 % 4;
    }
}

void enu ()
{
    for ( x[0] = 0; x[0] < 4; x[0] ++ )
    {
        for ( x[1] = 0; x[1] < 4; x[1] ++ )
        {
            for ( x[2] = 0; x[2] < 4; x[2] ++ )
            {
                for ( x[3] = 0; x[3] < 4; x[3] ++ )
                {
                    for ( x[4] = 0; x[4] < 4; x[4] ++ )
                    {
                        for ( x[5] = 0; x[5] < 4; x[5] ++ )
                        {
                            for ( x[6] = 0; x[6] < 4; x[6] ++ )
                            {
                                for ( x[7] = 0; x[7] < 4; x[7] ++ )
                                {
                                    for ( x[8] = 0; x[8] < 4; x[8] ++ )
                                    {
                                        if ( check () )
                                        {
                                            print ();
                                            goto out;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    out:
    return;
}

int main ()
{
    init ();
    enu ();
    return 0;
}

阅读(5487) | 评论(1)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册