1. 程式人生 > >POJ 1050(貪心,字首和,區間和)

POJ 1050(貪心,字首和,區間和)

#include<iostream>
#include<cstdio> 
#define ll long long 
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
int a[105][105],n;
int sum[105][105];
// 矩陣字首和
void init(){
	fo(i,1,n){
		fo(j,1,n){
			sum[i][j] = sum[i-1][j] + sum[i][j-1] + a[i][j] - sum[i-1][j-1];
		}
	}
}
// 查詢矩陣和## 標題
int query(int x1, int y1, int x2, int y2){
	return sum[x2][y2] - sum[x1-1][y2] - sum[x2][y1-1] + sum[x1-1][y1-1];
}
void solve(){
	int MAX = -1e8;
	fo(x1,1,n){
		fo(y1,1,n){
			fo(x2,x1,n){
				fo(y2,y1,n){
					int t = query(x1,y1,x2,y2);
					if(t>MAX) {
						MAX = t;
					//	cout<<x1<<" " <<y1<<" " <<x2<<" " <<y2<<endl;
					}
				}
			}
		}
	}
	printf("%d\n",MAX);
}
int main(){
	scanf("%d",&n);
	fo(i,1,n){
		fo(j,1,n){
			scanf("%d",&a[i][j]);
		}
	}
	init();
	solve();
	return 0;
}

貪心解法O(n^3) 優化為 類似一維陣列求最大連續序列和

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define fo(i,j,n) for(register int i=j; i<=n; ++i)
using namespace std;
const int maxn = 1e4;
int mp[maxn][maxn],n;
int d[maxn];
void solve(){
	int ans = mp[1][1];
	fo(i,1,n){ // i行 
		memset(d,0,sizeof(d)); 
		fo(j,i,n){ // j行 
			fo(k,1,n){ // k列 
				d[k] += mp[j][k]; // d[k] 表示第k列  第i~j行的和(區間和) 
			}
			
			// 接下來的做法就類似一維陣列求最大連續序列和 
			int sum = 0;
			fo(k,1,n){
				sum += d[k];
				ans = max(ans,sum);
				if(sum<0) sum=0;
			} 
		}
	}
	printf("%d\n", ans);
} 
int main(){
	while(scanf("%d",&n)==1){ // 使程式更加具有魯棒性 
		fo(i,1,n){
			fo(j,1,n)
				scanf("%d",&mp[i][j]);
		}
		solve();
	}
	return 0;
}