hdu 3688 模拟

题目大意:
方阵的某些格子里有灯,且其能照明的范围不一,只能在四个方向上照明;灯的亮度可调,求能够使得该位置有灯亮或者该位置的横向和纵向均有灯照明的可行的最小亮度

我想说,,,这种方法一般人谁想得到啊,不参考网上的做法,我真是不知道可以这样做,,,刚开始还想着用二分灯光亮度来写嘞;;;;

枚举横纵方向上两个灯之间距离,当两边都有灯时为之间距离的一半加一,特别的在边界上的情况要单独考虑

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define inf 0x3f3f3f3f
using namespace std;
int n,m,mp[109][10009],ans;
struct node
{
    int x,y,level,next[4];
    node(int a=0,int b=0,int c=0):x(a),y(b),level(c)
    {
        memset(next,-1,sizeof next);
    }
    void update();
} vex[109*10009];
void node::update()//当灯的亮度小于当前结果时将其关闭,更新四个方向上的灯的状态
{
    int left=next[0],right=next[2];
    if(left!=-1) vex[left].next[2]=right;
    if(right!=-1) vex[right].next[0]=left;
    if(left==-1&&right==-1) ans=inf;//此行上没有灯
    else if(left==-1) ans=max(ans,vex[right].y);//仅右边有灯
    else if(right==-1) ans=max(ans,m-vex[left].y+1);
    else ans=max(ans,(vex[right].y-vex[left].y+2)>>1);//两边都有灯时所需要的亮度为两灯之间距离的一半加一

    int up=next[1],down=next[3];
    if(up!=-1) vex[up].next[3]=down;
    if(down!=-1) vex[down].next[1]=up;
    if(up==-1&&down==-1) ans=inf;
    else if(up==-1) ans=max(ans,vex[down].x);
    else if(down==-1) ans=max(ans,n-vex[up].x+1);
    else ans=max(ans,(vex[down].x-vex[up].x+2)>>1);
}
int cmp(node a,node b)
{
    return a.level<b.level;
}
int main()
{
    while(scanf("%d%d",&n,&m)&&(n||m))
    {
        int tot=0;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=m; j++)
            {
                scanf("%d",&mp[i][j]);
                if(mp[i][j]) vex[++tot]=node(i,j,mp[i][j]);
            }
        sort(vex+1,vex+1+tot,cmp);
        for(int i=1; i<=tot; i++) mp[vex[i].x][vex[i].y]=i;
        ans=0;
        for(int i=1; i<=n&&ans!=inf; i++)
        {
            int pre=-1;
            for(int j=1; j<=m; j++)
            {
                if(mp[i][j])
                {
                    if(pre==-1) ans=max(ans,j);
                    else
                    {
                        ans=max(ans,(j-pre+2)>>1);
                        vex[mp[i][j]].next[0]=mp[i][pre];
                        vex[mp[i][pre]].next[2]=mp[i][j];
                    }
                    pre=j;
                }
            }
            if(pre==-1) ans=inf;
            else
                ans=max(ans,m-pre+1);//边界情况单独考虑
        }
        for(int i=1; i<=m&&ans!=inf; i++)
        {
            int pre=-1;
            for(int j=1; j<=n; j++)
            {
                if(mp[j][i])
                {
                    if(pre==-1) ans=max(ans,j);
                    else
                    {
                        ans=max(ans,(j-pre+2)>>1);
                        vex[mp[j][i]].next[1]=mp[pre][i];
                        vex[mp[pre][i]].next[3]=mp[j][i];
                    }
                    pre=j;
                }
            }
            if(pre==-1) ans=inf;
            else
                ans=max(ans,n-pre+1);
        }
        int i=1;
        while(i<=tot&&vex[i].level<ans&&ans<inf)
        {
            vex[i++].update();
        }
        if(ans==inf) puts("NO ANSWER!");
        else printf("%d\n",ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值