hdu6253 knightmare 【打表+找规律】

题意:象棋上的马可以向八个方向出棋,问一个马棋在走n步后,棋盘内有几个格子是有可能被走过的

 

想象一下出棋的过程,应该是一个由中心棋子不断向外扩散的画面,而且外层的棋子可能会相互覆盖,再看题目给出的样例数据,感觉应该是有规律可以找的,于是打表...

 

打表就用 bfs 的思想一层一层往外推 ...

打表的结果是酱紫的->


第一列是答案,第二列是 n+1 步的答案与 n 步的答案只差,第三列是他们差的差

可以非常开心得看到第三列的答案在第五步之后一直为28!!

们可以凭着这一点写出答案啦!!


不过在写的时候,要注意这道题数据 long long 会爆,需要用到无符号整形就能过了。

笔者因为这一点贡献了两个WA /(o)/~~

后来测试 1e9 的时候发现数据爆了才换成 unsigned long long

下面是打表和答案的代码

#include <iostream>  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <queue>  
using namespace std;  
  
int gram[505][505];  
  
struct point{  
    int x,y;  
    int layer;  
};  
  
int dir[8][2] = {{1,2},{1,-2},{2,1},{2,-1},{-1,2},{-1,-2},{-2,1},{-2,-1}};  
  
int main()  
{  
    memset(gram,0,sizeof(gram));  
    gram[205][205]=1;  
    queue<point> q;  
    point s;  
    s.x=100;s.y=100;  
    s.layer=0;  
    q.push(s);  
    int ans=1;  
    int ttt,tt;  
    for(int i=0;i<50;i++){  
        ttt = tt;  
        tt = 0;  
        while(1){  
            point p = q.front();  
            if(p.layer==i+1)  
                break;  
            q.pop();  
            for(int j=0;j<8;j++){  
                if(gram[p.x+dir[j][0]][p.y+dir[j][1]]==0){  
                    ans++;  
                    tt++;  
                    point np;  
                    np.layer=i+1;  
                    np.x=p.x+dir[j][0];  
                    np.y=p.y+dir[j][1];  
                    q.push(np);  
                    gram[p.x+dir[j][0]][p.y+dir[j][1]]=1;  
                }  
            }  
        }  
        printf("%dlayer: %d  %d %d\n",i+1,ans,tt,tt-ttt);  
    }  
  
    return 0;  
}  


#include <iostream>  
#include <stdio.h>  
  
using namespace std;  
  
int ans[7]={1,9,41,109,205,325,473};  
  
int main()  
{  
    int t;  
    scanf("%d",&t);  
    unsigned long long num;  
    for(int kase=1; kase<=t;kase++){  
        scanf("%llu",&num);  
        if(num<=6)  
            printf("Case #%d: %d\n",kase,ans[num]);  
        else{  
            unsigned long long t = num-6;  
            unsigned long long anss=473;  
            anss+=148*t;  
            unsigned long long tt = ((1+t)*t)/2;  
            anss+=28*tt;  
            printf("Case #%d: %llu\n",kase,anss);  
        }  
    }  
    return 0;  
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值