ZOJ2922 Bombs(搜索)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2922


参考学习的yamiedie_的博文:http://blog.csdn.net/u013654696/article/details/22313749


Bombs

Time Limit: 2 Seconds       Memory Limit: 65536 KB

A building has N*M rooms ( N rows and M columns 1<=N,M<=1000 ) . And there are bombs in some of these rooms. Each bomb has a power K which means when the bomb explodes, the K (K<1000) rooms on its left will all be destroyed, and the bombs in these rooms will explode automatically. The bomb has a special property, when a bomb exploded, the rooms above it will be destroyed and the bombs in these rooms will also explode automatically.

For example:

            A E I Q
            B F J R
            C G L S
            D H P T

When the bomb in room L explodes, and the power of that bomb is 1.Then the bombs in G and J and I will explode.

Now you task is to count at least how many bombs should be exploded by bomb expert so that all the bombs will explode.

Input

There are multiple test cases. There are two integers N and M on the first line of each case. In the next N lines followed, each line has M non-negative integers: K1 K2 ... KM, in which Ki is the power of the ith bomb. Ki=0 means there is no bomb in that room.

Process to the end of file.

Output

For each case, output the answer in a line, at least how many bombs should be exploded by bomb expert.

Sample Input


2 2
0 1
1 0
2 2
1 1
1 1
3 3
1 0 2
0 0 0
1 0 2
4 4
3 0 1 0
0 0 0 0
0 0 0 0
0 3 0 1

Sample Output


2
1
1
4


题意:在一个n*m的房间里,有些房间里有炸弹。如果一个炸弹引爆,那么位于它上面的所有房间中的炸弹都会引爆,同时引爆它左边的Ki个房间,炸弹的引爆具有连锁效应(即那些被引爆的炸弹也会像其他炸弹一样,引爆上面的房间和左边Kj个房间)。求出最少需要引爆几个炸弹才能让所有房间的炸弹全部爆炸。


可以发现炸弹总是向着左边和上边进行爆炸,所以从右下角开始搜索。

数组g表示每个炸弹的威力(K),0表示没有炸弹;ri表示该行ri个格子右边的炸弹已经全部引爆;v数组表示哪些列已经被引爆(从右下角开始枚举,因此每次可以引爆一整列)

每行的ri初始化为m+1

1. 如果当前房间没有炸弹,则继续搜索下一个房间

2. 如果当前房间有炸弹,那么看该列是否已经被引爆

  (1)如果该列已经被引爆,那么直接让炸弹爆炸,更新ri的值为min(ri,j-g[i][j])

  (2)如果该列还未被引爆

        ①如果j位于ri右边或等于ri,则表明j已经被引爆,将这列标记为引爆,并更新ri的值为min(ri,j-g[i][j])

        ②如果j位于ri左边,则表明j还没有被引爆,将需要引爆的炸弹数量(ans)+1,并引爆j(标记这列为引爆,并将ri更新为j-g[i][j])

最后输出ans的值即可。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;

int n,m,g[1005][1005];
int v[1005],ri;

int main()
{
    while (scanf("%d%d",&n,&m)!=EOF)
    {
          for (int i=1;i<=n;i++)
          {
              for (int j=1;j<=m;j++)
              {
                  scanf("%d",&g[i][j]);
              }
          }
          memset(v,0,sizeof(v));
          int ans=0;
          for (int i=n;i>0;--i)
          {
              ri=m+1;//初始化ri
              for (int j=m;j>0;--j)
              {
                  int wl=g[i][j];
                  if (g[i][j]==0) continue;//没有炸弹则继续搜索下一个房间
                  if (v[j]==0)
                  {
                     if (j>=ri)//情况①
                     {
                               v[j]=1;
                               ri=min(ri,j-g[i][j]);
                     }
                     else//情况②
                     {
                         ++ans;
                         v[j]=1;
                         ri=j-g[i][j];
                     }
                  }
                  else//情况(1)
                  {
                      ri=min(ri,j-g[i][j]);
                  }
              }
          }
          printf("%d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值