50095106扔核弹

50095106扔核弹

【试题描述】

     21xx年,ussr与us爆发了战争,us想将ussr肢解,于是毫不犹豫的准备使用战略核导弹。你现在正是战略打击部队的司令官,你收到了一幅由卫星发送的加密图片(n*m大小),在这张图片中“.”代表空地,“G”代表敌方军队,“#”代表三防(防核武,防化武,防自然威胁)设施。你的核弹当量极大,可以消灭杀伤范围内所有的暴徒。但你的核弹只能投送到空地上,且如果遇到了三防设施则不再构成杀伤范围(横着一行,竖着一行,碰到三防设施就不构成杀伤范围)。现在你的导弹发射架在(3,3)位置上,为了起到肢解效果,请你输出杀伤暴徒最多的方案,和最多可以杀死暴徒的个数(邪恶......)。

 

【输入要求】

* 第一行:两个整数n,m。
* 接下来是一张由“G”“#”“.”所构成的一张图,代表卫星发回的地图。 

 

【输出要求】

一句话如下格式
将导弹投送到(x,y),最多可以消灭z个敌人。

 

【输入实例】

13 13
#############
#GG.GGG#GGG.#
###.#G#G#G#G#
#.......#..G#
#G#.###.#G#G#
#GG.GGG.#.GG#
#G#.#G#.#.#.#
##G...G.....#
#G#.#G###.#G#
#...G#GGG.GG#
#G#.#G#G#.#G#
#GG.GGG#G.GG#
#############

 

【输出实例】

将导弹投送到(7,11),最多可以消灭10个敌人。

 

【其他说明】

LJX认为n与m不会大于26。

 

【试题分析】

LJX李家鑫小朋友出的数据貌似有点坑,输出的格式在中英文上面很复杂~~~

我们先来看一看怎么求投掷在一个点消灭的敌人吧,当然,四个简单的while就能解决,代码如下:

int res(int i,int j)
{
    int sum=0,l,b;
    l=i;//这里一定不要忘了备份,否则i和j的值以后就不能用了。
    b=j;
    while(a[l][b]!='#')//当不是三防设施的时候
    {
        if(a[l][b]=='G') sum++;//是敌人,sum加1
        b++;//威力向左移动
    }
    l=i;//备份
    b=j;
    while(a[l][b]!='#')
    {
        if(a[l][b]=='G') sum++;
        b--;//向右移动
    }
    l=i;//备份
    b=j;
    while(a[l][b]!='#')
    {
        if(a[l][b]=='G') sum++;
        l++;//向上移动
    }
    l=i;
    b=j;
    while(a[l][b]!='#')
    {
        if(a[l][b]=='G') sum++;
        l--;
    }//向下移动
    return sum;//返回结果
}

这就可以了。

然后,暴力搜索一遍:

int main()
{
    for(int i=0;i<n;i++)//枚举每一个点
        for(int j=0;j<m;j++)
        {
             sum=res(i,j);
             ans=max(ans,sum);//如果结果大就替换
        }
     cout<<ans;
}

把这两段代码合起来,再加上声明和头文件and输出格式就对了

对吗?

也许你已经看出漏洞来了,如果只是单单投送到任意空地上的话,那么答案貌似就不是点(7,11)了吧?

可以试着运行一下上面这个程序,还要加上记录点,貌似是右上角那个空地,能消灭11个敌人。

实际上,这还是一个迷宫问题,当然,我们可以用dfs搞定,代码如下:

void dfs(int x,int y)
{
     int next[4][2]={{0,1},//走向数组
                     {1,0},
                     {0,-1},
                     {-1,0}};
     int sum,tx,ty,k;
     sum=res(x,y);//求出打在这里的答案
     if(sum>maxn)//大了的话替换
     {
         maxn=sum;
         mx=x;
         my=y;
     }
     for(k=0;k<=3;k++)
     {
         tx=x+next[k][0];
         ty=y+next[k][1];
         if(tx<0 || tx>n-1 || ty<0 || ty>m-1) continue;//边界判断
         if(a[tx][ty]=='.' && book[tx][ty]==0)//可以走且没走到过
         {
             book[tx][ty]=1;//标记已走
             dfs(tx,ty);//继续行走
         }
     }
     return ;
}

【代码】

#include<iostream>
using namespace std;
char a[50][50];
int maxn=-10000,book[50][50],n,m,mx,my;
int res(int i,int j)
{
    int sum=0,l,b;
    l=i;
    b=j;
    while(a[l][b]!='#')
    {
        if(a[l][b]=='G') sum++;
        b++;
    }
    l=i;
    b=j;
    while(a[l][b]!='#')
    {
        if(a[l][b]=='G') sum++;
        b--;
    }
    l=i;
    b=j;
    while(a[l][b]!='#')
    {
        if(a[l][b]=='G') sum++;
        l++;
    }
    l=i;
    b=j;
    while(a[l][b]!='#')
    {
        if(a[l][b]=='G') sum++;
        l--;
    }
    return sum;
}
void dfs(int x,int y)
{
     int next[4][2]={{0,1},
                     {1,0},
                     {0,-1},
                     {-1,0}};
     int sum,tx,ty,k;
     sum=res(x,y);
     if(sum>maxn)
     {
         maxn=sum;
         mx=x;
         my=y;
     }
     for(k=0;k<=3;k++)
     {
         tx=x+next[k][0];
         ty=y+next[k][1];
         if(tx<0 || tx>n-1 || ty<0 || ty>m-1) continue;
         if(a[tx][ty]=='.' && book[tx][ty]==0)
         {
             book[tx][ty]=1;
             dfs(tx,ty);                  
         }
     }
     return ;
}
int main()
{
    int i,startx=3,starty=3;
    cin>>n>>m;
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            cin>>a[i][j];
    book[startx][starty]=1;
    maxn=res(startx,starty);
    mx=3;
    my=3;
    dfs(3,3);
    cout<<"将导弹投送到("<<mx<<","<<my<<"),最多可以消灭"<<maxn<<"个敌人。";
}
posted @ 2016-06-24 09:43  wxjor  阅读(258)  评论(0编辑  收藏  举报