USACO第一章最后一题(相当悲剧...)

      好久没来了!!!大二了,确实比较忙啊,这学期就这么结束了,又要放寒假回家过年咯....

      最近在做USACO上面的题目,立志要把上面的题全部 K.O.掉。 嘿嘿.....第一章还花了我一些时间,第一章的入门题还都是我自己独立完成的,有些题很简单,也有些还比较有价值,能有所收获。收获最大的就数最后一个题了,哎....说起来都悲剧啊,眼看着就要完成第一章了,却被这个题卡了两天啊。也不是不会做这个题,好不容易写出代码来,觉得时间应该不成问题,可惜就是超时了(限时一秒,我大约1.6秒),其实也就是最后一组测试数据13超时了,在我实在是不知道我的代码还能怎么优化来节约时间的时候,我还是决定用最不常用的也最怕用的指针创建链表来修改程序中的一些部分,估计能节约一点时间出来,还是修改了半天终于把指针改对了,不容易啊....,但是运行了一下,还是悲剧,基本上没节约时间。

         好吧,我换方法,定义一个map[15][15]记录棋盘,放一颗棋就划掉它的列和对角线上的地方。又好不容易写出来了代码,自己运行一下,当输入6,7,8的时候是对的,输入9,10,11,12,13的时候就错了,我这就抓狂了,把代码看了一遍又一遍,不知道哪出了问题,在无意之间,我把我的所有变量拖到外面去,全部定义为全局变量,发现居然输入 9,10也对了,但11,12,13还是不对。我茫然了.....还有这种怪事,定义全局变量和定义局部变量还对程序有影响???搞得我丈二和尚,摸不到头脑了都。整的我晚上的觉都没睡好,没办法还是得研究啊,今天早上起床继续,还不信有找不出来的错误。我但不调试,不厌其烦地试了各种方法,输出中间值,研究到了中午,在单步调试的时候,我发现在某个时刻,程序经过某一个语句的时候,一个和该语句没有关系的变量的值居然奇迹般由1变为了2,然后我继续,又在某个时刻经过另一个语句的时候,该变量由2又变为1。我知道问题就出在这里,可是我还是很茫然,他到底是怎么变的呢?这个语句跟变化的这个变量一点关系也没有。那最后就定位这个语句有什么问题???可是这个语句是我常用的语句啊,以前经常用都没有出现过任何问题啊,那为什么输入小点的数就没问题,而输入大数就出问题了呢???我还是来研究研究这个语句吧...经过一番考证之后我发现了新大陆,原来以前我用的这个语句都是错的,只是这个错误一直潜伏着,到了今日才酿成了苦果。这到底是个什么样的错误呢?就是一个简单的for循环语句,带有两个控制循环结束的条件语句。 for(i=a,j=b; i<c,j>d; i++,j--) s[i][j]=1; 就是这个我以前经常用到的,我一直以为是正确的。我以为 i<c和j>d两个条件同时成立才执行循环体,错了,i<c,j>d是一个逗号表达式,逗号表达式的值等于最右边的一个表达式的值,也就是j>d的值。要达到我想要的目的只能写成 i<c&&j>d; 一定要铭记啊!!! 改正程序之后再提交,发现虽然比前一种方法快点,但还是数据13的时间比1秒多点,超时。

         无奈之下,我上USACO的中文翻译网站nocow上面去看了看,原来上面不仅有翻译还有大家的讲解啊,很不错,讲了很多种方法。我看了一个递归的代码,跟我的第一种方法差不多,用col[j]记录第j列是否被占,但我用搜索的方法看两个点是否在一条对角线上,这个浪费了不少时间,他的代码巧妙地用diag1[i+j]和diag2[i-j-MAXN]记录每条对角线是否被占。当两个点(i,j)(p,q)在同一条'/'对角线上有i+j==p+q;在同一条'/'对角线上有i- j==p-q; 于是我按照这个思路,再把我第一个代码优化了一下。最后一运行,0.7秒,啊... 终于OK了,赶快提交,我又郁闷了,它告诉我还是超时了,我就奇怪了,在我电脑上0.7 秒,他运行的就是1.1秒了,我无语....难道堂堂的USACO的服务器还没有我的电脑运行速度快?? 不可能吧?? 没办法,在借鉴一下别人的对半求的方法,再优化了一半的时间。这下终于过了...... 系统告诉我提交了17次......我什么也不说了.......

#include <stdio.h>

#define MAXN 15

int n;
int nsol, nprinted;
char row[MAXN], col[MAXN], diag1[2*MAXN], diag2[2*MAXN];

void nway(int i, int lim)
{
    int j, k;

    if(i == n)
    {
        nsol++;
        if (n > 6 && row[0] < n/2) nsol++;
        if (nprinted++ < 3)
        {
            for(k=0; k<n-1; k++)
                printf("%d ", row[k]+1);
            printf("%d/n", row[n-1]+1);
        }
        return;
    }
    for(j=0; j<lim; j++)
    {
        if (col[j] || diag1[i+j] || diag2[i-j+MAXN]) continue;
        row[i] = j;
        col[j] = 1;
        diag1[i+j] = 1;
        diag2[i-j+MAXN] = 1;
        nway(i+1, n);
        col[j] = 0;
        diag1[i+j] = 0;
        diag2[i-j+MAXN] = 0;
    }
}

int main()
{
    freopen("checker.in", "r", stdin);
    freopen("checker.out", "w", stdout);
    scanf("%d", &n);
    nway(0, n>6?(n+1)/2:n);
    printf("%d/n", nsol);
    exit(0);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值