USACO1.4 The Clocks 解题报告

第一次用BFS,以前只是会用递归的DFS搜索,这次对照着书,硬生生的把BFS打出来了,终于明白什么叫做复杂度了。

先上程序(很明显这题的BFS会很痛苦,因为第一层9个,第二层9×9,第三层9×9×9,大约到了8层的时候,无论是什么样的队列,还是堆栈都不崩溃了)

很悲惨,到了第三组数据的时候完全不可能通过了,队列溢出了。实在无法达到35亿的储存效果。希望和我一样遇到这个问题的小白注意一下子。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<fstream>
using namespace std;
char means[10][6]= {"","ABDE","ABC","BCEF","ADG","BDEFH","CFI","DEGH","GHI","EFHI"};
int clockx[10],t[11];
int queue[3000000][11];
long long int qs=0,qe=0;
int stack[1000],sp=0;
int p;
int inthequeue(int t[])
{
    int flag=1;
    for(int i=0;i<=qe&&flag;i++)
        for(int j=1;j<=9&&flag;j++)
            if(t[j]!=queue[i][j])
                flag=0;
    return flag;
}
int check(int t[10])
{
    int flag=1;
    for(int i=1; i<=9&&flag; i++)
        if(t[i]!=12)    flag=0;
    return flag;
}
int main()
{
    int i,j,flag=1;
    ifstream cin("clocks.in");
    ofstream cout("clocks.out");
    for(i=1; i<=9; i++)
        cin>>clockx[i];
    for(j=1; j<=10; j++)
        queue[qs][j]=clockx[j];
    queue[qe][0]=0;
    qe++;
    for(j=1; j<=9; j++)  t[j]=queue[qs][j];
    while(1)
    {
        for(i=1; i<=9; i++)
        {
            for(j=1; j<=9; j++)  t[j]=
            queue[qs][j];
            for(j=0; j<strlen(means[i]); j++)
            {
                p=means[i][j]-'A'+1;
                t[p]+=3;
                if(t[p]>12) t[p]=3;
            }
            if(inthequeue(t));
            else{for(j=1; j<=10; j++)
                queue[qe][j]=t[j];
            queue[qe][0]=qs;
            queue[qe][10]=i;}
            if(check(t))
            {
                flag=0;
                break;
            }
            qe++;
        }
        if(!flag)   break;
        qs++;
    }
    j=queue[qe][0];
    stack[sp]=queue[qe][10];
    sp++;
    while(j!=0)
    {
        stack[sp]=queue[j][10];
        sp++;
        j=queue[j][0];
    }
    for(j=sp-1; j>0; j--)
        cout<<stack[j]<<" ";
    cout<<stack[0]<<endl;
    return 0;
}

然后呢,难以剪枝的BFS最终还是被我放弃了,参考了一下网上各位大牛的思路。

貌似这一题是90年代IOI上的题目,还是poj上的原题,写出解题报告的大牛真不少。

一位大牛所说,需要使用高斯消去定理(我汗。这个真不会),还有一位大牛说,需要用到线性代数里面的矩阵(想想也是啊,可是。。线代我也不会。。),最后一位OI同学提到了可以直接枚举就可以解决问题,我也仔细一想,果然,仅仅是3^9的复杂度,每次旋转九十度,只与次数(0.1.2.3次)有关,不和顺序有关。所以我就有了这样很娱乐的方法。。如此做来相当飘逸。。

#include<iostream>
#include<string.h>
#include<fstream>
using namespace std;
char means[10][6]= {"","ABDE","ABC","BCEF","ADG","BDEFH","CFI","DEGH","GHI","EFHI"};
int clocks[10],t[11];
int x[10];
int check(int t[10])
{
    int flag=1;
    for(int i=1; i<=9&&flag; i++)
        if(t[i]!=12)    flag=0;
    return flag;
}
int main()
{
    int i,j,k,p;
    ifstream cin("clocks.in");
    ofstream cout("clocks.out");
    for(i=1; i<=9; i++)
        cin>>clocks[i];
    for(x[1]=0; x[1]<=3; x[1]++)
     for(x[2]=0; x[2]<=3; x[2]++)
      for(x[3]=0; x[3]<=3; x[3]++)
       for(x[4]=0; x[4]<=3; x[4]++)
        for(x[5]=0; x[5]<=3; x[5]++)
         for(x[6]=0; x[6]<=3; x[6]++)
          for(x[7]=0; x[7]<=3; x[7]++)
           for(x[8]=0; x[8]<=3; x[8]++)
            for(x[9]=0; x[9]<=3; x[9]++)
            {
                for(j=1; j<=9; j++)  t[j]=clocks[j];
                for(i=1; i<=9; i++)
                    for(k=1; k<=x[i]; k++)
                    for(j=0; j<strlen(means[i]); j++)
                    {
                        p=means[i][j]-'A'+1;
                        t[p]+=3;
                        if(t[p]>12) t[p]=3;
                    }
                    if(check(t))
                    {
                        i=1;
                        while(x[i]==0)  i++;
                        cout<<i;
                        for(j=2; j<=x[i]; j++)
                            cout<<" "<<i;
                        for(i++; i<=9; i++)
                        {
                            for(j=1; j<=x[i]; j++)
                                cout<<" "<<i;
                        }
                        cout<<endl;
                        return 0;
                    }
            }
    return 0;
}

感觉不用BFS实在对不住这道题目。。我会慢慢学习大牛的BFS算法是如何炉火纯青的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值