SCU 4487 king's trouble I(dfs)||(0找1)

46 篇文章 0 订阅
 king's trouble I

Description

Long time ago, a king occupied a vast territory. Now there is a problem that he worried that he did not know how much of the perimeter of his territory. Can you help him? For simplicity, we use a matrix to represent the territory as follows: 0 0 0 0 0 0 1 0 1 0 1 1 0 1 0 0 1 1 0 0 0 0 1 0 0 Every single number in the matrix represents a piece of land, which is a 1*1 square 1 represents that this land has been occupied 0 represents not Obviously the perimeter of all ocupied lands is 20

Input

The first line of the input contains a single integer t (1≤t≤5) — the number of cases. For each case The first line has two integers N and M representing the length and width of the matrix Then M lines follows to describe the matrix 1≤N,M≤400

Output

For each case output the perimeter of all ocupied lands

Sample Input

1 5 5 0 0 0 0 0 0 1 0 1 0 1 1 0 1 0 0 1 1 0 0 0 0 1 0 0

Sample Output

20
原题链接:http://acm.scu.edu.cn/soj/problem.action?id=4487

ps:整整在比赛中浪费了3个小时的大水题0.0,还是看图找线索的能力不够

别人的思想是:先在外围加一圈0,然后对每一个0寻找它旁边的1或着是对每一个1寻找它旁边的0,最后加起来就行了

然而我没有看出来那个规律,所以用了dfs走迷宫,每次dfs时第一步加4条边,其他步能走时加两条边,如果碰到已经走过的说明有边相交这时要减两条边,但是在走的过程中老是多加边或者是多减边,调代码调了3个多小时。。。。。最后还是直接每一步全部先加4条边,最后对每一个为1的点只判断它的右边和下面是不是1,是的话就减边,最后终于A了

代码:
#include<stdio.h>
#include<string.h>

#define maxn 400+10
#define mem(a,b) memset(a,b,sizeof(a))
int to[][2]= {0,1,1,0,0,-1,-1,0};
int a[maxn][maxn],vis[maxn][maxn];
int n,m,ans;

void dfs(int x,int y)
{
    for(int i=0; i<4; i++)
    {
        int xx=x+to[i][0],yy=y+to[i][1];
        if(xx>=0&&xx<n&&yy>=0&&yy<m&&a[xx][yy])
        {
            if(!vis[xx][yy])
            {
                ans+=4;
                vis[xx][yy]=1;
                dfs(xx,yy);
            }
        }
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {

        mem(vis,0);
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                scanf("%d",&a[i][j]);
        ans=0;
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            {
                if(a[i][j]&&!vis[i][j])
                {
                    ans+=4;
                    vis[i][j]=1;
                    dfs(i,j);
                }
            }
        mem(vis,0);
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            {
                if(a[i][j])
                {
                    for(int k=0; k<2; k++)
                    {
                        int xx=i+to[k][0],yy=j+to[k][1];
                        if(xx>=0&&xx<n&&yy>=0&&yy<m&&a[xx][yy])
                        {
                                ans-=2;
                        }
                    }
                }
            }
        printf("%d\n",ans);
    }
    return 0;
}

总结:写这道题时看别人都A的那么快,可能心里面也有一点慌,所以只顾着debug了,就没有想到换一条思路,最后还是比赛快结束了实在没办法了,才去认真的思考这道题,想到方法
所以,一道题如果别人都A了而自己迟迟都不行的话,十有八九是自己的思路有问题,要谨记适时调整思路
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值