1. 程式人生 > 其它 >[2021.8集訓Day4/JZOJ.4754] 【GDOI2017模擬9.4】矩陣

[2021.8集訓Day4/JZOJ.4754] 【GDOI2017模擬9.4】矩陣

目錄

[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;
}