bzoj1897. tank tank game (decision monotony of divide and conquer)

Title Description

There is such a new tank game. In the game, you will manipulate a tank, complete a task in a region of N × M in. In this area, there will be many targets to attack, and you destroy such a goal each, will get equal to the target value score. Only received the highest score, the task is completed. Meanwhile, in order to increase the authenticity and difficulty of the game, the game also made the following restrictions:

1) Tank limited range of r. For purposes of calculation, a range of r defined as: target (x1, y1) when the tank is located in (x, y) grid, it may attack must satisfy | x-x1 |, | y-y1 | ∈ [0, r].

2) there are strict limitations on the tank to complete the task in time, defined as t seconds. Wherein, once the mobile tanks are each 1 second required, also need to attack a target every 1 second. To a time t seconds, then the task of scoring.

3) Tank initially in the upper left corner, and is only allowed to move to the right or downward direction, allowing only a moving grid.

In the above restrictions, to complete the task will become a very difficult thing. Therefore, you must write a program to this end, let it help you complete this arduous task.

Input Format

The first line of four integers N, M, r, t, respectively, represent the region of the length, width, and the range and time to complete the task.

The next line N is a matrix of N × M, the value corresponding to the target at each location.

Output Format

Only a few output file max, i.e., the highest score obtainable task.

Sample

Sample input

5 5 2 7
0 5 0 0 4
0 0 0 0 2
0 0 0 0 0
0 0 0 0 0
5 0 3 0 11

Sample Output

21

Data range and tips

1≤N、M≤500,1≤r≤100,1≤t≤250。

For 20% of the data we have: 1≤N, M≤10.

For 60% of the data we have: 1≤N, M≤50,1≤r≤10.

For 80% of the data we have: 1≤N, M≤100,1≤r≤20.


 

Set $ ​​f [i] [j] [k] $ express to $ (i, j) $ $ k $ hit up one of the largest value

He notes that the number of targets hit each step must be monotonic not drop

Divide and conquer monotony of decision-making by optimizing every time you transfer

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define re register
using namespace std;
int read(){
    char c=getchar(); int x=0;
    while(c<'0'||c>'9') c=getchar();
    while('0'<=c&&c<='9') x=x*10+c-48,c=getchar();
    return x;
}
#define N 505
int cmp(int A,int B){return A>B;}
int n,m,R,T,ans,k=1,a[N][N],f[2][N][253],h[N*N],tp,g[N],v[N];
void solve(int l,int r,int dl,int dr){
    if(l>r||dl>dr) return ; 
    int mm=(l+r)/2,dm=dl;
    for(int i=dl;i<=min(mm,dr);++i)
        if(v[mm]<g[mm-i]+h[i])
            v[mm]=g[mm-i]+h[i],dm=i;
    solve(l,mm-1,dl,dm);
    solve(mm+1,r,dm,dr);
}
int main(){
    n=read(); m=read(); R=read(); T=read();
    for(re int i=1;i<=n;++i)
        for(re int j=1;j<=m;++j)
            a[i][j]=read();
    for(re int i=1;i<=R+1;++i)
        for(re int j=1;j<=R+1;++j)
            if(a[i][j]) h[++tp]=a[i][j];
    sort(h+1,h+tp+1,cmp); tp=min(tp,T);//注意最多取T个
    for(re int i=1;i<=tp;++i) f[1][1][i]=f[1][1][i-1]+h[i];
    int _n=max(1,n-R),_m=max(1,m-R);
    for(re int i=1;i<=_n;++i,k^=1)
        for(re int j=1;j<=_m;++j){
            int lim=T-i-j+2;
            if(lim<=0) continue;
            if(i>1){
                for(re int u=0;u<=lim;++u) v[u]=g[u]=f[k^1][j][u];
                tp=0;
                for(re int u=max(1,j-R);u<=min(m,j+R);++u)
                    if(a[i+R][u]) h[++tp]=a[i+R][u];
                sort(h+1,h+tp+1,cmp);
                for(re int u=1;u<=tp;++u) h[u]+=h[u-1];
                solve(1,lim,0,tp);
                for(re int u=0;u<=lim;++u) f[k][j][u]=max(f[k][j][u],v[u]);
            }
            if(j>1){
                for(re int u=0;u<=lim;++u) v[u]=g[u]=f[k][j-1][u];
                tp=0;
                for(re int u=max(1,i-R);u<=min(n,i+R);++u)
                    if(a[u][j+R]) h[++tp]=a[u][j+R];
                sort(h+1,h+tp+1,cmp);
                for(re int u=1;u<=tp;++u) h[u]+=h[u-1];
                solve(1,lim,0,tp);
                for(re int u=0;u<=lim;++u) f[k][j][u]=max(f[k][j][u],v[u]);
            }
            while(lim) ans=max(ans,f[k][j][lim--]);
        }
    printf("%d",ans);
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/kafuuchino/p/11359685.html