hdu 3630 Crystal mine

來源:互聯網
上載者:User
Crystal mine

Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 528    Accepted Submission(s): 86

Problem DescriptionLegends always begin with the sentence “Long long ago......”
Long long ago, there is a kingdom. The border of this kingdom is rectangular, and some lakes in it. Old king divides land to N * M areas. So, we can regard this kingdom as a matrix. Every element of matrix is an area. This kingdom is famous for crystal mine,
because every land contains an ocean of crystal underground, except lakes.
Now, the old king wants to build a large rectangular mine field in a rectangular range which is decide by him. What’s more, he wants to build a special area in mine field, which can produce crystal manyfold. Notice that mine field can't contain lakes. Unfortunately,
the old king is too old to remember something. He always asks his adviser this question with different range.
Adviser is tired of answering those questions day by day. So, you are assigned to solve this problem. You get the kingdom map, and the amount of crystal of every area (as A[][]) has been marked on this map. You should find out the best plan to build this mine
field which can produce most crystal. Old king never care the details of plan. The only thing he wants know is the number of crystal the mine field can produce. 

InputThere are several test cases in the input file.
The first line of input file contains a number T, representing the number of test cases. For each test case:
First line contains four integers separated by a single blank, N (1 <= N <= 150), M (1 <= M <= 150), Q (1<= Q <= 200), S (1 <= S <= 10). The size of matrix is N * M. Q indicates the number of questions of old king. S indicates that, if you set the special area
in (i,j), (i,j) will produce S * A[i][j] instead of A[i][j].
The following N lines, each line contains M number, the j-th number of i-th line represent A[i][j] (-1 <= A[i][j] < 100 ). Number -1 indicates that, this area is a lake. Otherwise A[i][j] indicates the amount of crystal in this area.
Following Q line, each line contains four integers p, q, x, y. (1 <= p <= x <= N, 1 <= q <= y <= M) indicating the rectangular range of this question is from (p,q) to (x,y). (p,q) is upper left corner of range, and (x,y) is lower right corner of range. 

OutputFor each test case, first line should contains “Case #: ”, ”#”is case number (starting from 1). Each of the following Q line contains a number indicating the answer of question.
Look at sample output for more details. There is a blank line between two consecutive test cases. 

Sample Input

14 4 3 21 -1 0 31 1 2 02 1 0 -11 4 6 11 1 1 11 1 3 31 3 3 4
 

Sample Output

Case 1:298題意:給你一個地圖  再給你一個矩陣範圍  讓你在這個矩陣中找到一個不包含-1的子矩陣 且這個子矩陣的和+S*(max-1) 最小 (max 為這個子矩陣的和的最大值)思路:用最大子矩陣方法枚舉出滿足條件的矩陣 預先處理後能直接對子矩陣求和 然後用二維RMQ求最大值 然後更新ans感想:其實思路並不難  題目也並不是太難  不過坑了我和我的老大幾天額 ╮(╯▽╰)╭  我們的複雜度降到O(n^3)了 但還是TLE 好蛋疼 感謝網友ice_crazy 我們是從他的代碼中找到了是什麼卡了我們的時間   二維RMQ時求log(n)/log(2) 這個打一個表就夠了   因為不打表的話就會算O(n^3)次  會很拖時間的  
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;const int maxn = 155;int a[maxn][maxn];int mp[maxn][maxn];int power[maxn];int ssum[maxn][maxn];                       // 對二維數組預先處理 方便求子矩陣和int dp[maxn][maxn][9][9];int h[maxn][maxn],le[maxn][maxn],ri[maxn][maxn];int n,m,q,ans,sum,s;int maxx(int xx,int yy){    return xx>yy?xx:yy;}void init_rmq(){    for(int i=0; (1<<i)<=n; i++)    {        for(int j=0; (1<<j)<=m; j++)        {            if(i==0 && j==0)                continue;            for(int row=1; row+(1<<i)-1<=n; row++)            {                for(int col=1; col+(1<<j)-1<=m; col++)                {                    if(i==0)                    {                        dp[row][col][i][j] =                            maxx(dp[row][col][i][j-1],dp[row][col+(1<<(j-1))][i][j-1]);                    }                    else                    {                        dp[row][col][i][j] =                            maxx(dp[row][col][i-1][j],dp[row+(1<<(i-1))][col][i-1][j]);                    }                }            }        }    }}int query(int x1,int y1,int x2,int y2){    int kx=power[x2-x1+1];    int ky=power[y2-y1+1];    int m1=dp[x1][y1][kx][ky];    int m2 = dp[x2-(1<<kx)+1][y1][kx][ky];    int m3 = dp[x1][y2-(1<<ky)+1][kx][ky];    int m4 = dp[x2-(1<<kx)+1][y2-(1<<ky)+1][kx][ky];    return maxx( maxx(m1,m2), maxx(m3,m4) );}void left(int hang)                   // 向左擴充{    int i,j;    h[hang][0]=-2;    for(i=1; i<=m; i++)    {        if(h[hang][i]>0)        {            le[hang][i]=1;            while(h[hang][i-le[hang][i]]>=h[hang][i])            {                le[hang][i]+=le[hang][i-le[hang][i]];            }        }    }}void right(int hang)                  // 向右擴充{    int i,j;    h[hang][m+1]=-2;    for(i=m; i>=1; i--)    {        if(h[hang][i]>0)        {            ri[hang][i]=1;            while(h[hang][i+ri[hang][i]]>=h[hang][i])            {                ri[hang][i]+=ri[hang][i+ri[hang][i]];            }        }    }}void init_maxarrey()                    // 對矩陣做求最大子矩陣的預先處理  {    int i,j;    for(i=1; i<=n; i++)    {        for(j=1; j<=m; j++)        {            if(mp[i][j]>0) h[i][j]=h[i-1][j]+1;            else h[i][j]=0;        }        left(i);        right(i);    }}void solve(int u1,int v1,int u2,int v2){    int i,j,k,ss;    int xx1,xx2,yy1,yy2,temps;    ans=0;    for(i=u1; i<=u2; i++)    {        for(j=v1; j<=v2; j++)        {            if(h[i][j]>=0)               // 這裡的判斷條件不要加錯了  我開始加的是 h[i][j]-h[u1][j]>=0 不能這麼加             {                xx1=maxx(i-h[i][j]+1,u1);                yy1=maxx(j-le[i][j]+1,v1);                xx2=i;                yy2=j+ri[i][j]-1<v2?j+ri[i][j]-1:v2;                temps=query(xx1,yy1,xx2,yy2);                ss=ssum[xx2][yy2]-ssum[xx2][yy1-1]-ssum[xx1-1][yy2]+ssum[xx1-1][yy1-1]+temps*(s-1);                if(ans<ss) ans=ss;            }        }    }}int main(){    int i,j,t,t1,k;    for(i=1;i<=150;i++)                 // 打表很重要    {        power[i]=log(double(i))/log(2.0);    }    scanf("%d",&t);    for(k=1; k<=t; k++)    {        scanf("%d%d%d%d",&n,&m,&q,&s);        memset(ssum,0,sizeof(ssum));        for(i=1; i<=n; i++)        {            for(j=1; j<=m; j++)            {                scanf("%d",&a[i][j]);                dp[i][j][0][0]=a[i][j];                ssum[i][j]=a[i][j]+ssum[i-1][j]+ssum[i][j-1]-ssum[i-1][j-1];                if(a[i][j]>=0) mp[i][j]=1;                else mp[i][j]=-1;            }        }        init_rmq();        init_maxarrey();        if(k>1) printf("\n");        printf("Case %d:\n",k);        while(q--)        {            int x1,y1,x2,y2;            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);            solve(x1,y1,x2,y2);            printf("%d\n",ans);        }    }    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.