USACO 2012 January Contest, Bronze Division

在达尔的指导下,第一次做了这类比赛,

在 Observers 里面的成绩:

CHNChuanshun Yuan833
********x*

**********

*xxx*x****
排了30+,被达尔戈狠狠地鄙视了一下。


A题,莫名其妙地第9个数据挂,还是没有弄清为啥错了。其实A题还是有些值得说的,

首先,标程的分析中认为排序后先把小的部分累加,那么最后不能加的那个用做是否使用打折扣?为什么可以这样,我也纳闷。

其次,达尔戈说的一次排序(O(nlogn))后,枚举每个cow( O(n) )使用打折扣,然后是对每个枚举到的要统计一个和来逼近S,显然这里是二分可以快速完成,所以总的时间复杂度O( nlog(n) ),即使n<=10^6也是可以做的,何况题目n<=1000;


B题,线段树直接写,达尔说 “铜赛这水平的还要用线段树么”,反正我是直接写的,有标记延迟,最后一个所有节点的递归得到最终的值。


C题,这种题最不会了,而且犯浑了一下,我是枚举第一头牛到达中点的情况,再验证第二头牛是否能在指定条件下到达中点,挂得很惨。。。

标程的分析:

        A much simpler way to look at this problem is to simply countall possible self-avoiding walks from (1,1) to (5,5) that cover all the valid squares.That is, we pretend that there is just one cow who wants to move from (1,1) to (5,5),instead of there being two cows moving at the same time. It is easy to see that thereis a one-to-one correspondence between paths involving two cows meeting halfway (as in the original problem statement) and paths involving just one cow who starts at (1,1)and ends at (5,5); the midpoint of the one-cow path would correspond to the meetingpoint in the analogous two-cow solution.

         Now that we know we need to count paths from (1,1) to (5,5), we proceed to enumerateand count all such paths with a recursive function. The "count" function below does thisby temporarily noting that the current square is blocked (so we don't return there),temporarily incrementing the blocked square count K, and then recursively visiting allneighbors, accumulating the counts we get from each of them.

也即,根据题目需求,可以等价于使第一头牛从(1,1)到(5,5)走一遍的路的总数,而且标程写的十分nb,我从来没有见过这种写法。果断学习之

【C题标程】

#include <cstdio>
#include <cmath>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define MM(a,b) memset(a,b,sizeof(a));
typedef unsigned long long u64;
typedef long long lld;
#define maxn

bool map[10][10];
int K;

int count(int x,int y){
    int c;
    if(x<0||x>4||y<0||y>4||map[x][y]!=0) return 0;
    map[x][y]=1;
    K++;
    if( K==25 && x==4 && y==4 ) c=1;
    else
        c= count(x-1,y)+count(x+1,y)+count(x,y-1)+count(x,y+1);
    map[x][y]=0;
    K--;
    return c;
}    
int main()
{
    while(cin>>K){
        MM( map, 0 );
        for(int i=0;i<K;++i){
            int x,y;
            scanf("%d%d",&x,&y);
            map[x-1][y-1]=1;
        }    
        int ans= count(0,0);
        printf("%d\n",ans);
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值