JDOJ-最小面積子矩陣 暴力(排斥二分)


這題就是求一個矩陣中的最小面積矩陣,使得其和大於一個給定的K,由於是求最優解,所以很自然的想到了二分查找這個值,但是這題我卻在不去頂是否滿足二分性質的前提下匆忙的選擇了二分查找,最終導致了錯誤。原因在與當一個面積為一個最優解的時候,面積大於該最優解的子矩陣不一定包含這個最優矩陣,例如一個5*5的矩陣的,如果最優矩陣是一個2*2的矩陣,那么1*5的面積為5的矩陣式不會包含這個2*2的矩陣的,所以......

代碼如下:

#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 105
using namespace std;

int N, M, K, G[MAXN][MAXN], S[MAXN*MAXN], lim;
int rec[MAXN*MAXN], idx, sum[MAXN][MAXN];

struct Node
{
    int x, y;
}que[MAXN];

int front, tail;

inline void pre()
{
    int k;
    lim = N*M;
    memset(S, 0, sizeof (S));
    idx = -1;
    // getstatus
    for (int i = 1; i <= N; ++i) {
        k = min(M, lim / i); // 選取相對小的值,排除不合法情況
        for (int j = 1; j <= k; ++j) {
            S[i*j] = 1;
        }
    }
    for (int i = 1; i <= lim; ++i) {
        if (S[i]) {
            rec[++idx] = i;
        }
    }
    // getsum
    for (int i = 1; i <= N; ++i) {
        for (int j = 1; j <= M; ++j) {
            sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + G[i][j];
        }
    }
}

bool judge()
{
    int xx, yy, zz, lx, ly;
    for (int k = 1; k <= tail; ++k) {
        lx = N - que[k].x + 1, ly = M - que[k].y + 1;
        for (int i = 1; i <= lx; ++i) {
            for (int j = 1; j <= ly; ++j) {
                xx = i+que[k].x-1, yy = j+que[k].y-1; 
                if (xx <= N && yy <= M) {
                    zz = sum[xx][yy] - sum[i-1][yy] - sum[xx][j-1] + sum[i-1][j-1];
                    if (zz >= K) return true;
                }
            }
        }
    }
    return false;
}

bool Ac(int x) // 能夠保證所有的x都是合法值 
{
    front = tail = 0;
    for (int i = 1; i <= N; ++i) {
        if (x % i == 0) {
            ++tail;
            que[tail].x = i, que[tail].y = x / i;
        }
    } // 處理處當前面積的分解情況
    if (judge()) {
        return true;
    }
    return false;
}

int bsearch(int l, int r)
{
    int mid, ret = -1;
    while (l <= r) {
        mid = (l + r) >> 1;
        if (Ac(rec[mid])) {
            ret = rec[mid];
            r = mid - 1;
        }
        else {
            l = mid + 1;    
        }
    }
    return ret;
}

int force()
{
    for (int i = 0; i <= idx; ++i) {
        if (Ac(rec[i])) {
            return rec[i];
        }    
    }
    return -1;
}

int main()
{
    while (scanf("%d %d %d", &N, &M, &K) != EOF) {
        for (int i = 1; i <= N; ++i) {
            for (int j = 1; j <= M; ++j) {
                scanf("%d", &G[i][j]);
            }
        }
        pre();
    //    printf("%d\n", bsearch(0, idx));
        printf("%d\n", force());
    }
    return 0;    
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM