题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2922
参考学习的yamiedie_的博文:http://blog.csdn.net/u013654696/article/details/22313749
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
可以发现炸弹总是向着左边和上边进行爆炸,所以从右下角开始搜索。
数组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;
}