【搜索】[HDU1175]连连看

题目
分析:这道题看到的第一反应应该就是BFS或者DFS,裸的DFS、BFS显然会TLE,所以我就想用A*,不过好像并不好写启发函数。
枚举步数不行,就枚举边吧。因为允许有两次转折,所以最多有三条边枚举中间的一条边,然后进行check,这道题只用了两个for循环就AC了。

代码:

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
#define MAXN 1000
int a[MAXN+10][MAXN+11],q,n,m,h[MAXN+10][MAXN+10],v[MAXN+10][MAXN+10],sx,sy,ex,ey;
bool check(){
    int i,a,b;
    a=min(sx,ex);
    b=max(sx,ex);
    for(i=1;i<=m;i++){
        if(i<sy){
            if(h[sx][sy-1]!=h[sx][i-1])
                continue;
        }
        else if(i>sy){
            if(h[sx][sy]!=h[sx][i])
                continue;
        }
        if(i<ey){
            if(h[ex][ey-1]!=h[ex][i-1])
                continue;
        }
        else if(i>ey){
            if(h[ex][ey]!=h[ex][i])
                continue;
        }
        if(sy==i&&ey==i){
            if(v[b-1][i]!=v[a][i])
                continue;
        }
        else if(sy==i){
            if(sx<ex){
                if(v[ex][i]!=v[sx][i]);
                    continue;
            }
            else if(sx>ex){
                if(v[sx-1][i]!=v[ex-1][i])
                    continue;
            }
        }
        else if(ey==i){
            if(sx>ex){
                if(v[ex][i]!=v[sx][i]);
                    continue;
            }
            else if(sx<ex){
                if(v[sx-1][i]!=v[ex-1][i])
                    continue;
            }
        }
        else if(v[b][i]!=v[a-1][i])
            continue;
        return 1;
    }
    a=min(sy,ey);
    b=max(sy,ey);
    for(i=1;i<=n;i++){
        if(i<sx){
            if(v[i-1][sy]!=v[sx-1][sy])
                continue;
        }
        else if(i>sx){
            if(v[i][sy]!=v[sx][sy])
                continue;
        }
        if(i<ex){
            if(v[i-1][ey]!=v[ex-1][ey])
                continue;
        }
        else if(i>ex){
            if(v[i][ey]!=v[ex][ey])
                continue;
        }
        if(sx==i&&ex==i){
            if(h[i][b-1]!=h[i][a])
                continue;
        }
        else if(sx==i){
            if(sy<ey){
                if(h[i][ey]!=h[i][sy])
                    continue;
            }
            else if(sy>ey){
                if(h[i][sy-1]!=h[i][ey-1])
                    continue;
            }
        }
        else if(ex==i){
            if(sy>ey){
                if(h[i][ey]!=h[i][sy])
                    continue;
            }
            else if(sy<ey){
                if(h[i][sy-1]!=h[i][ey-1])
                    continue;
            }
        }
        else if(h[i][b]!=h[i][a-1])
            continue;
        return 1;
    }
    return 0;
}
int main()
{
    int i,j;
    while(scanf("%d%d",&n,&m)){
        if(!n)
            return 0;
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++){
                scanf("%d",&a[i][j]);
                h[i][j]=h[i][j-1]+a[i][j];
                v[i][j]=v[i-1][j]+a[i][j];
            }
        scanf("%d",&q);
        while(q--){
            scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
            if(a[sx][sy]!=a[ex][ey]||!a[sx][sy]||!check())
                puts("NO");
            else
                puts("YES");
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值