社区讨论

学校题求调(时间超限)题目不难

学术版参与者 4已保存回复 7

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
7 条
当前快照
1 份
快照标识符
@lq3q6zxr
此快照首次捕获于
2023/12/13 20:06
2 年前
此快照最后确认于
2023/12/13 22:45
2 年前
查看原帖
题目: 现在有一个n * m的矩阵,小x想要从中找到两个互不相交且大小为k * k的子矩阵,使得两个矩阵的元素和相加最大。
一直t 求调
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=1550;
typedef long long ll;
int a[N][N],g[N][N],n,m,k,cnt;
ll ans=-1;
struct node{
	int x,y,v;
	bool operator<(const node&p)const{
		return v>p.v;
	}
}f[N*N];
bool check(int x1,int y1,int x2,int y2){
	if(y1+k<=y2||y1>=y2+k)return 1;
	else if(x1+k<=x2||x1>=x2+k)return 1;
	else return 0;
}
int main(){
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			cin>>a[i][j],g[i][j]=g[i][j-1]+a[i][j]+g[i-1][j]-g[i-1][j-1];//g维护一个前缀和 
	for(int i=1;i<=n-k+1;i++)
		for(int j=1;j<=m-k+1;j++)
			f[++cnt].v=g[i+k-1][j+k-1]-g[i-1][j+k-1]-g[i+k-1][j-1]+g[i-1][j-1],f[cnt].x=i,f[cnt].y=j;//f存每一个k*k的值 
	sort(f+1,f+cnt+1);
	for(int i=1;i<cnt;i++){//找出两个最大的值且不重叠 ,从大到小找
		if(f[i].v+f[i+1].v<ans)break;//最大都不行就说明找完了 
		for(int j=i+1;j<=cnt;j++){
			if(f[i].v+f[j].v<ans)break; 
			if(check(f[i].x,f[i].y,f[j].x,f[j].y)&&f[i].v+f[j].v>ans){//不重叠且比已知的大,那就更新 
				//cout<<f[i].x<<" "<<f[i].y<<" "<<f[j].x<<" "<<f[j].y<<endl;
				ans=f[i].v+f[j].v;
				break;//之后的j无意义 
			}
		}
	}
	cout<<ans;
	return 0;
}

回复

7 条回复,欢迎继续交流。

正在加载回复...