zoukankan      html  css  js  c++  java
  • 【51NOD1487】占领资源

    题面

    有一个矩形区域被划分为N行M列的网格,每个格子里有一定数量的资源并记录在矩阵val中,坐标(x,y)位置上资源量为val[x][y],其val中每个元素的值为0~9的整数。如果你在某个网格(a,b)上造一座保护塔,那么你可以占领K个网格中的资源,这K个格子分别是(a+dx[1],b+dy[1]),(a+dx[2],b+dy[2]),...,(a+dx[K],b+dy[K]),注意(a,b)这格本身可能未必会被占领。现在你能建造不超过2个塔,问最多能占领多少资源?一个网格被多个塔占领时其资源只计算一次。另外如果计算的位置(a+dx[i],b+dy[i])在网格外,则不贡献任何资源。
    Input
    多组测试数据,第一行一个整数T,表示测试数据数量,1<=T<=5
    每组测试数据有相同的结构构成:
    每组数据第一行三个整数N,M,K,其中2<=N,M<=100,1<=K<=10。
    之后会有N行,每行M个元素,表示val矩阵。每个元素为0~9,占一个字符,元素间没空格。
    再接下来有K行,每行两个整数dx[i]与dy[i],其中-(N-1)<=dx[i]<=N-1,-(M-1)<=dy[i]<=(M-1).

    分析

    首先肯定2个炮台都要建的,但是 n*m*k=1e5,为什么不暴力枚举在每个点呢?哦,需要枚举2个点。。那就是1e10了。
    用数据结构优化一下?是放在线段树专题的题,然而实在看不出来用线段树维护啥啊??
    机房julao稍微点拨了一下,我在重整了一下思路。如果没有每个点的贡献只能出现一次的话,就直接枚举每个点找次大和最大值了。
    但是有了这个限制,然而有一句话,你爸爸始终是你爸爸【雾
    所以即便是最大和次大有重复的点,相对来说,它们还是更大的,至少你要权值较大,你才能可能成为被选的点之一。
    于是我们就不止用最大和次大,还得算3大,4大……这些组合起来的总贡献,反正不超时的情况下,尽量多选一些点来试一试。优先队列维护一下。
    理是这个理,但是稍微设计一下数据就好容易被卡掉qvq。不过真的是个可爱的暴力呢

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define N 110
    int t,n,m,k,tot,ans;
    int dx[N],dy[N],a[N][N],vis[N][N];
    char s[N];
    struct email
    {
        int x,y,v;
    };
    bool operator <(email q1,email q2)
    {
        return q1.v<q2.v;
    }
    priority_queue<email>q;
    inline email mp(int x,int y,int v){email c;c.x=x,c.y=y,c.v=v;return c;}
    inline void init(){memset(vis,0,sizeof(vis));while(!q.empty())q.pop();ans=0;tot=10;}
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            init();
            scanf("%d%d%d",&n,&m,&k);
            for(int i=1;i<=n;i++)
            {
                scanf("%s",s);
                for(int j=1;j<=m;j++)
                    a[i][j]=s[j-1]-'0';
            }    
            for(int i=1;i<=k;i++)scanf("%d%d",&dx[i],&dy[i]);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                {
                    int sum=0;
                    for(int o=1;o<=k;o++)
                    {
                        int tx=dx[o],ty=dy[o];
                        if(i+tx>=1&&i+tx<=n&&j+ty>=1&&j+ty<=m)
                            sum+=a[i+tx][j+ty];
                    }    
                    q.push(mp(i,j,sum));
                }
            while(!q.empty()&&tot)    
            {
                tot--;
                email e=q.top();q.pop();
                int px=e.x,py=e.y,now=e.v;
                for(int o=1;o<=k;o++)
                {
                    int tx=dx[o],ty=dy[o];
                        if(px+tx>=1&&px+tx<=n&&py+ty>=1&&py+ty<=m)
                            vis[px+tx][py+ty]=tot;
                }
                for(int i=1;i<=n;i++)
                {
                    for(int j=1;j<=m;j++)
                    {
                        int sum=0;
                        for(int o=1;o<=k;o++)
                        {
                            int tx=dx[o],ty=dy[o];
                            if(vis[i+tx][j+ty]==tot)continue;
                            if(i+tx>=1&&i+tx<=n&&j+ty>=1&&j+ty<=m)
                                sum+=a[i+tx][j+ty];
                        }    
                        ans=max(ans,sum+now);    
                    }        
                }
            }
            printf("%d
    ",ans);        
        }
        return 0;
    }
    “Make my parents proud,and impress the girl I like.”
  • 相关阅读:
    「实战」攻防中钓鱼上线MAC终端
    JAVA审计SQL注入
    使用Netcat实现通信和反弹Shell
    通过Mssql提权的几种姿势
    第三方提权之ServU提权
    使用LCX进行内网端口转发
    Proxifier/ProxyChains+reGeorg组合进行内网代理
    通过Mysql提权的几种姿势
    java:文件与IO
    java:常用类库api
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9787880.html
Copyright © 2011-2022 走看看