hdu 1045 Fire Net(贪心)

小记:这题是暑期训练放在贪心这一章的题,我瞎蒙的, 没想到真的对了


思路:我的这个想法,我自己试了几组数据,也试图去举出点反例,但是都没用,答案都是正确的,而且也比较的简单可行,所以我抱着试试的态度做了。

贪心的思路就是,对方格的每个点记录下它上下左右四个方向所能覆盖的点的个数,

即因为你要放在这点上的话,那么这点的上下左右四个方向就不能再放了,当然碰到墙就打止

例如:

 
 
4 .X.. .... XX.. ....
题目这组数据

那么转化过来就是

2 0 5 5

5 4 7 7

0 0 5 5

4 4 7 7

就这样

然后对个数值进行从小到大排序,依次选择,选择了该点之后,那么它所覆盖的点都不能在被选择了,标记起来即可。

答案就是你所选择的点的个数


代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>

using namespace std;

#define mst(a,b) memset(a,b,sizeof(a))
#define REP(a,b,c) for(int a = b; a < c; ++a)
#define eps 10e-8

const int MAX_ = 110;
const int N = 100010;
const int INF = 0x7fffffff;

struct node{
    int s, e;
    int num;
}t[MAX_];

int vis[MAX_][MAX_];
char str[MAX_][MAX_];


bool cmp(const node& a, const node& b)
{
    return a.num < b.num;
}

int main()
{
	int T;
	int n, m;
	//scanf("%d",&T);
	while(scanf("%d",&n), n) {
	    REP(i, 0, n){
            scanf("%s", str[i]);
	    }
	    int cnt = 0;
        //mst(vis, 0);
	    REP(i, 0, n){
            REP(j, 0, n){
                if(str[i][j] == '.'){
                    vis[i][j] = 0;
                    int tmp = 0;
                    int h = 0;
                    while(i-h > -1 && str[i-h][j] == '.'){h++; tmp++;}

                    h = 1;
                    while(i+h < n && str[i+h][j] == '.'){h++; tmp++;}

                    h = 1;
                    while(j-h > -1 && str[i][j-h] == '.'){h++; tmp++;}

                    h = 1;
                    while(j+h < n && str[i][j+h] == '.'){h++; tmp++;}

                    t[cnt].s = i;
                    t[cnt].e = j;
                    t[cnt].num = tmp;
                    cnt++;
                }else vis[i][j] = 1;
            }
	    }
        sort(t, t+cnt, cmp);


	    int ans = 0;
	    REP(i, 0, cnt){
	        int x = t[i].s, y = t[i].e;
            if(!vis[x][y]){
                ans++;
                int h = 0;
                while(x-h > -1 && str[x-h][y] == '.'){vis[x-h][y] = 1;h++; }

                h = 1;
                while(x+h < n && str[x+h][y] == '.'){vis[x+h][y] = 1;h++; }

                h = 1;
                while(y-h > -1 && str[x][y-h] == '.'){vis[x][y-h] = 1;h++; }

                h = 1;
                while(y+h < n && str[x][y+h] == '.'){vis[x][y+h] = 1;h++; }

            }
	    }

	    printf("%d\n", ans);

	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值