hdu校赛—1005

航海舰队

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
Byteasar组建了一支舰队!他们现在正在海洋上航行着。
海洋可以抽象成一张 n×m 的网格图,其中有些位置是''.'',表示这一格是海水,可以通过;有些位置是''#'',表示这一格是礁石,不可以通过;有些位置是''o'',表示这一格目前有一艘舰,且舰离开这一格之后,这一格将变为''.''。
这些''o''表示Byteasar的舰队,他们每天可以往上下左右中的一个方向移动一格,但不能有任何一艘舰驶出地图。特别地,Byteasar对阵形有所研究,所以他不希望在航行的过程中改变阵形,即任何时刻任何两艘舰的相对位置都不能发生变化。
Byteasar的舰队可以航行无限长的时间,每当一艘舰经过某个格子的时候,这个格子海底的矿藏都将被Byteasar获得。请写一个程序,帮助Byteasar计算他最多可以获得多少个格子海底的矿藏?
 

Input
第一行包含一个正整数 T(1T15) ,表示测试数据的组数。
每组数据第一行包含两个正整数 n,m(1n,m50) ,分别表示地图的长和宽。
接下来 n 行,每行有 m 个字符,每个字符只能是''.''、''#''、''o''中的一个。
输入数据保证至少有一个''o''。
 

Output
输出 T 行,每行格式为''Case #i:  ans ''(不含引号), i 表示测试数据的编号, ans 表示答案。
 

Sample Input
  
  
2 3 3 ... .o# .#. 4 5 ....# .o#.o .o..o ..o..
 

Sample Output
  
  
Case #1: 6 Case #2: 12
 
【分析】
暴搜....不要觉得点多搜起来慢,其实点越多搜起来越快,因为越容易撞到墙
因为这道题有很多点的移动,所以容易出现细节问题,可以考虑先把这个图周围加上一圈墙,这样的话就不用考虑边界了。只要考虑墙就可以了。
然后就是简单的去判断对每次所有点向同一个方向能否移动,然后搜下去就可以了。
这里有一点,不要考虑所有点,抓住一个点,移动,其他点跟着它动就可以了,这里我的dfs记录情况是所有点横纵移动的步数(因为传数组会炸内存)
很考验细节和基础的一道题~
【代码】
#include<stdio.h>
#include <string.h>
int x1[1000];
int y1[1000];
char s[60][60];
int f[60][60];
int a[60][60];
int ff[10];
int flag;
int n,m,len,ans;


void check(int x,int y)
{
    flag=0;
    int t=0;
    if (a[x1[len]-1+x][y1[len]+y]) t=1;
    else
        for (int i=0;i<len;i++)
            if (s[x1[i]-1+x][y1[i]+y]=='#')
            {
                t=1;break;
            }
    if (!t) ff[flag++]=1;
    t=0;
    if (a[x1[len]+1+x][y1[len]+y]) t=1;
    else
        for (int i=0;i<len;i++)
            if (s[x1[i]+x+1][y1[i]+y]=='#')
            {
                t=1;break;
            }
    if (!t) ff[flag++]=2;
    t=0;
    if (a[x1[len]+x][y1[len]+y+1]) t=1;
    else
        for (int i=0;i<len;i++)
            if (s[x1[i]+x][y1[i]+y+1]=='#')
            {
                t=1;break;
            }
    if (!t) ff[flag++]=3;
    t=0;
    if (a[x1[len]+x][y1[len]+y-1]) t=1;
    else
        for (int i=0;i<len;i++)
            if (s[x1[i]+x][y1[i]-1+y]=='#')
            {
                t=1;break;
            }
    if (!t) ff[flag++]=4;
}
void find(int x,int y)
{
    a[x1[len]+x][y1[len]+y]=1;
    check(x,y);
    int fl=flag;
    int fa[10];
    for (int i=0;i<fl;i++) fa[i]=ff[i];
    for (int i=0;i<fl;i++)
    {
        if (fa[i]==1)
        {
            for (int j=0;j<=len;j++) ans+=f[x1[j]+x-1][y1[j]+y],f[x1[j]+x-1][y1[j]+y]=0;
            find(x-1,y);
        }
        if (fa[i]==2)
        {
            for (int j=0;j<=len;j++) ans+=f[x1[j]+x+1][y1[j]+y],f[x1[j]+x+1][y1[j]+y]=0;
            find(x+1,y);
        }
        if (fa[i]==3)
        {
            for (int j=0;j<=len;j++) ans+=f[x1[j]+x][y1[j]+y+1],f[x1[j]+x][y1[j]+y+1]=0;
            find(x,y+1);
        }
        if (fa[i]==4)
        {
            for (int j=0;j<=len;j++) ans+=f[x1[j]+x][y1[j]+y-1],f[x1[j]+x][y1[j]+y-1]=0;
            find(x,y-1);
        }
    }
}

int main()
{
    int pp;scanf("%d",&pp);
    for (int p=1;p<=pp;p++)
    {
        len=0;
        memset(f,0,sizeof(f));
        memset(s,0,sizeof(s));
        memset(a,0,sizeof(a));
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
        {
            getchar();
            for (int j=1;j<=m;j++)
            {
                scanf("%c",&s[i][j]);
                if (s[i][j]=='.') f[i][j]=1;
                if (s[i][j]=='o')
                {
                    s[i][j]='.';
                    x1[len]=i;
                    y1[len]=j;
                    len++;
                }
                if (s[i][j]=='#') a[i][j]=1;
            }
        }
        for (int i=0;i<n+2;i++) s[i][0]='#',s[i][m+1]='#',a[i][0]=1,a[i][m+1]=1;
        for (int i=0;i<m+2;i++) s[0][i]='#',s[n+1][i]='#',a[0][i]=1,a[n+1][i]=1;
        ans=len;
        len--;
        find(0,0);
        printf("Case #%d: %d\n",p,ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值