hdu 4331 Image Recognition

Image Recognition


先处理出每个位置,前后左右四个方向的连续的1的个数。。由于正方形的对角顶点一定在对角线上,所以直接暴力枚举。

#include <cstdio>
#include <cstring>
const int maxn = 1005;
int l[maxn][maxn];
int r[maxn][maxn];
int u[maxn][maxn];
int d[maxn][maxn];
int a[maxn][maxn];
int n;

void init(){
    memset(l, 0, sizeof(l));
    memset(r, 0, sizeof(r));
    memset(u, 0, sizeof(u));
    memset(d, 0, sizeof(d));
}

void work(){
    //left and up
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= n; j ++){
            if(a[i][j]==0){
                l[i][j] = 0;
                u[i][j] = 0;
            }
            else{
                l[i][j] = l[i][j - 1] + 1;
                u[i][j] = u[i - 1][j] + 1;
            }
        }
    }
    //right and down
    for(int i = n; i >= 1; i --){
        for(int j = n; j >= 1; j --){
            if(a[i][j]==0){
                r[i][j] = 0;
                d[i][j] = 0;
            }
            else{
                r[i][j] = r[i][j + 1] + 1;
                d[i][j] = d[i + 1][j] + 1;
            }
        }
    }
}

struct Node{
    int x ;
    int L,R;
}point[maxn];

int min(int x, int y){
    if(x < y)
        return x;
    return y;
}

int findans(int x, int y){
    int ret = 0 ;
    int s = 0;
    int m = 0;
    for(int i = x, j= y ; i <= n && j <= n; i ++, j ++){
        ++ s;
        point[m].x = s;
        point[m].R = s + min(r[i][j], d[i][j]) - 1;
        point[m].L = s - min(l[i][j], u[i][j]) + 1;
        ++ m;
    }

    for(int i = 0; i < m; i ++){
        for(int j = i + 1; j < m; j ++){
            if(point[i].R >= point[j].x && point[j].L <= point[i].x){
                ++ ret;
            }
        }
    }
    return ret;
}

int solve(){
    //枚举所有斜线的起点
    int ans = 0;
    for(int i = 1; i < n; i++)
        ans += findans(i, 1);
    for(int j = 2; j < n; j++)
        ans += findans(1, j);
    return ans;
}

int main(){
    int t;
    int cas = 1;
//    freopen("test.in", "r", stdin);
    scanf("%d", &t) ;
    while(t--){
        scanf("%d", &n);
        init();
        int ans = 0;
        for(int i = 1; i <= n; i ++){
            for(int j = 1; j <= n; j ++){
                scanf("%d", &a[i][j]);
                if(a[i][j]==1)
                    ans ++;
            }
        }
        //处理出l,r,u,d四个数组的值
        work();
        //得到答案
        printf("Case %d: %d\n", cas++, ans + solve());
    }
    return 0 ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值