zoukankan      html  css  js  c++  java
  • [51Nod1487]占领资源

    题目大意:
    ​  有一个$n imes m(x,mleq 100)$的网格图,每个格子有一个权值$w_{i,j}(1leq w_{i,j}leq 9)$。你可以在图中选两个格子,每个格子$(x,y)$可以接收$k(kleq 10)$个格子,$(x+dx[1],y+dy[1]),(x+dx[2],y+dy[2]),ldots,(x+dx[k],y+dy[k])$的权值。超出边界的能量不接收,每个格子的权值最多被接收一次,问最多能接收多少权值。

    思路:
    ​  考虑选择不同格子,吸收权值的范围不相交的情况,我们可以直接暴力$O(nmk)$求出每个点能吸收的权值,然后选两个最大的加起来即可。
    ​  现在每个格子的吸收范围可能会相交,因此我们还需要分两种情况考虑。
      我们可以先求出每个点能吸收的权值,然后找出吸收范围会和该点重合的点,不难发现这样的点最多只有$k^2$个。
      对于会相交的点,我们暴力求一下可以吸收哪些点的权值,对于不相交的点,可以直接用稀疏表求区间最大值,时间复杂度$O(nmk^2log(nm))$。

      1 #include<set>
      2 #include<cstdio>
      3 #include<cctype>
      4 #include<algorithm>
      5 inline int getint() {
      6     register char ch;
      7     register bool neg=false;
      8     while(!isdigit(ch=getchar())) if(ch=='-') neg=true;
      9     register int x=ch^'0';
     10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     11     return neg?-x:x;
     12 }
     13 inline int getblock() {
     14     register char ch;
     15     while(!isdigit(ch=getchar()));
     16     return ch^'0';
     17 }
     18 typedef std::pair<int,int> Point;
     19 const int N=100,K=10,logN2=15;
     20 std::set<Point> set;
     21 bool vis[N*N],b[N][N];
     22 int n,m,k,a[N][N],dx[K],dy[K],max[N*N][logN2],q[K*K+3];
     23 inline bool check(const int &x,const int &y) {
     24     return x>=0&&x<n&&y>=0&&y<m;
     25 }
     26 inline int id(const int &x,const int &y) {
     27     return x*m+y;
     28 }
     29 inline int log2(const float &x) {
     30     return ((unsigned&)x>>23&255)-127;
     31 }
     32 inline int query(const int &l,const int &r) {
     33     const int k=log2(r-l+1);
     34     return std::max(max[l][k],max[r-(1<<k)+1][k]);
     35 }
     36 inline int calc(const int &x1,const int &y1) {
     37     int ret=q[0]=0;
     38     for(register int i=0;i<k;i++) {
     39         const int x3=x1+dx[i],y3=y1+dy[i];
     40         if(!check(x3,y3)) continue;
     41         b[x3][y3]=true;
     42         for(register int j=0;j<k;j++) {
     43             const int x2=x3-dx[j],y2=y3-dy[j];
     44             if(!check(x2,y2)||vis[id(x2,y2)]) continue;
     45             vis[q[++q[0]]=id(x2,y2)]=true;
     46         }
     47     }
     48     for(register int i=1;i<=q[0];i++) {
     49         vis[q[i]]=false;
     50     }
     51     q[++q[0]]=-1;
     52     q[++q[0]]=n*m;
     53     std::sort(&q[1],&q[q[0]+1]);
     54     for(register int i=1;i<q[0];i++) {
     55         if(q[i]+1<=q[i+1]-1) {
     56             ret=std::max(ret,query(q[i]+1,q[i+1]-1));
     57         }
     58     }
     59     for(register int i=2;i<q[0];i++) {
     60         const int x2=q[i]/m,y2=q[i]%m;
     61         int tmp=0;
     62         for(register int i=0;i<k;i++) {
     63             const int x3=x2+dx[i],y3=y2+dy[i];
     64             if(!check(x3,y3)||b[x3][y3]) continue;
     65             tmp+=a[x3][y3];
     66         }
     67         ret=std::max(ret,tmp);
     68     }
     69     for(register int i=0;i<k;i++) {
     70         const int x3=x1+dx[i],y3=y1+dy[i];
     71         if(!check(x3,y3)) continue;
     72         b[x3][y3]=false;
     73     }
     74     return ret;
     75 }
     76 int main() {
     77     for(register int T=getint();T;T--) {
     78         n=getint(),m=getint(),k=getint();
     79         for(register int i=0;i<n;i++) {
     80             for(register int j=0;j<m;j++) {
     81                 a[i][j]=getblock();
     82             }
     83         }
     84         for(register int i=0;i<k;i++) {
     85             dx[i]=getint(),dy[i]=getint();
     86             if(set.count((Point){dx[i],dy[i]})) {
     87                 i--,k--;
     88             } else {
     89                 set.insert((Point){dx[i],dy[i]});
     90             }
     91         }
     92         set.clear();
     93         for(register int x=0;x<n;x++) {
     94             for(register int y=0;y<m;y++) {
     95                 for(register int i=max[id(x,y)][0]=0;i<k;i++) {
     96                     if(!check(x+dx[i],y+dy[i])) continue;
     97                     max[id(x,y)][0]+=a[x+dx[i]][y+dy[i]];
     98                 }
     99             }
    100         }
    101         for(register int j=1;j<=log2(n*m);j++) {
    102             for(register int i=0;j<=log2(n*m-i);i++) {
    103                 max[i][j]=std::max(max[i][j-1],max[i+(1<<(j-1))][j-1]);
    104             }
    105         }
    106         int ans=0;
    107         for(register int x1=0;x1<n;x1++) {
    108             for(register int y1=0;y1<m;y1++) {
    109                 ans=std::max(ans,max[id(x1,y1)][0]+calc(x1,y1));
    110             }
    111         }
    112         printf("%d
    ",ans);
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    SharePoint 2010 网站备份还原简单介绍
    SharePoint 2010 常用技巧及方法总结
    Javascript 中的window.parent ,window.top,window.self 详解
    SharePoint2013 此产品的试用期已结束
    SharePoint 2013 showModalDialog 弹出模式窗口
    SharePoint文档库,如何在新窗口打开中的文件
    sharepoint2013- Office web app server2013详细的安装和部署
    SharePoint 2013 入门教程之入门手册
    SharePoint 解决打开浏览器自动登录
    解决IIS进程回收后第一次访问慢的问题
  • 原文地址:https://www.cnblogs.com/skylee03/p/8260271.html
Copyright © 2011-2022 走看看