[2021.8集訓Day4/JZOJ.4754] 【GDOI2017模擬9.4】矩陣
阿新 • • 發佈:2021-08-12
目錄
[2021.8集訓Day4/JZOJ.4754] 【GDOI2017模擬9.4】矩陣
題目
思路
挺水的一道題,也是Day4唯一能做的一道題.
關鍵的一句話就是矩陣中的每個數非負.
換句話說就是一個矩陣的權值不小於它的子矩陣.
又看到\(k\)比較小,我們把最小的和諧矩陣(\(mina\times minb\)的矩陣)扔到小根堆裡,每次從小根堆取出一個矩陣並進行擴充套件(右邊界,下邊界分別擴寬1),把擴充套件後的矩陣扔進堆裡,可以證明,取出的矩陣權值是單調不下降的,所以進行\(k-1\)次後,在堆頂的矩陣即為所求.
需要注意的就是矩陣判重和爆int
.
矩陣判重可以map可以Hash,也可以通過過載運算子,讓相同的矩陣在相鄰的時刻中從堆裡取出來,方便判斷.
矩陣大小\(1000\times 1000\),元素之和就是\(3\times 10^9>2,147,483,647\).可以用unsigned int
居然因為長和寬弄反卡了幾十分鐘.
程式碼
#include <iostream> #include <cstdio> #include <queue> #define int unsigned using namespace std; int read() { int re = 0; char c = getchar(); bool negt = false; while(c < '0' || c > '9') negt |= (c == '-') , c = getchar(); while(c >= '0' && c <= '9') re = (re << 1) + (re << 3) + c - '0' , c = getchar(); return negt ? -re : re; } const int N = 1010; const int K = 250000; struct Matrix { unsigned short x1 , y1 , x2 , y2; int sum; bool operator < (const Matrix &b) const { return sum > b.sum; } }; class Hashing { private : static const int mod = 1000007; typedef long long lint ; typedef unsigned long long ulint ; struct CHAIN { signed nxt; ulint key; } chain[K * 7]; int head[mod + 10]; inline ulint hash(Matrix a) { return ((a.x1 * N + a.y1) * N + a.x2) * N + a.y2; } int cnt; public : bool find(Matrix a) { ulint key = hash(a); for(int i = head[key % mod] ; i ; i = chain[i].nxt) { if(chain[i].key == key) return true; } ++cnt; chain[cnt].key = key , chain[cnt].nxt = head[key % mod] , head[key % mod] = cnt; return false; } } hash_; int a[N][N]; int sum[N][N]; int n , m , mina , minb , k; int GetSum(int x1 , int y1 , int x2 , int y2) { return sum[x2][y2] + sum[x1 - 1][y1 - 1] - sum[x2][y1 - 1] - sum[x1 - 1][y2]; } inline Matrix push(int x1 , int y1 , int x2 , int y2) { Matrix tmp; tmp.x1 = x1 , tmp.x2 = x2 , tmp.y1 = y1 , tmp.y2 = y2 , tmp.sum = GetSum(x1 , y1 , x2 , y2); return tmp; } signed main() { n = read() , m = read() , mina = read() , minb = read() , k = read(); for(int i = 1 ; i <= n ; i++) for(int j = 1 ; j <= m ; j++) a[i][j] = read(); 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] + a[i][j]; priority_queue <Matrix> q; for(int i = 1 ; i + mina - 1 <= n ; i++) for(int j = 1 ; j + minb - 1 <= m ; j++) q.push(push(i , j , i + mina - 1 , j + minb - 1)) , hash_.find(push(i , j , i + mina - 1 , j + minb - 1)); for(int i = 1 ; i < k ;) { if(q.empty()) break; Matrix mat = q.top(); q.pop(); if(mat.x2 + 1 <= n) if(!hash_.find(push(mat.x1 , mat.y1 , mat.x2 + 1 , mat.y2))) q.push(push(mat.x1 , mat.y1 , mat.x2 + 1 , mat.y2)); if(mat.y2 + 1 <= m) if(!hash_.find(push(mat.x1 , mat.y1 , mat.x2 , mat.y2 + 1))) q.push(push(mat.x1 , mat.y1 , mat.x2 , mat.y2 + 1)); ++i; } if(q.empty()) puts("-1"); else cout << (q.top()).sum; return 0; }