# Simulation# Array# Greedy

f313 - 2. 人口遷移

🔗 前往 ZeroJudge 原題

題目描述

題目給定一個 R x C 的城市網格,每個城市都有一定的人口數。每天,每個城市會將其人口數除以 k 的整數部分,平均分配給其相鄰的城市(上下左右)。要求模擬 m 天後,城市人口數的最大值和最小值。如果某個位置沒有城市(人口數為 -1),則該位置不能作為人口遷移的起點或終點。

解題思路

這題的核心是模擬人口遷移的過程。使用一個二維陣列 a 儲存城市的人口數,另一個二維陣列 b 儲存每天的人口變化量。 每次迭代(代表一天),計算每個城市需要遷移的人口,並將其分配給相鄰的城市。 為了避免修改原始陣列 a 時出現問題,使用輔助陣列 b 記錄每天的人口變化量,然後在每次迭代結束後,將 b 的值加到 a 上。 模擬 m 天後,遍歷 a 陣列,找到人口數的最大值和最小值。

複雜度分析

  • 時間複雜度: O(r * c * m),其中 r 是列數,c 是行數,m 是天數。因為需要模擬 m 天,每天需要遍歷整個網格。
  • 空間複雜度: O(r * c),因為需要使用兩個 r x c 的陣列 ab 儲存城市的人口數和人口變化量。

程式碼

#include <iostream>
using namespace std;
int a[51][51],r,c,k,m,b[51][51];
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	cin >> r >> c >> k >> m;
	for(int i=0;i<r;++i)
		for(int j=0;j<c;++j)
			cin >> a[i][j];
	while(m--){
		for(int i=0;i<r;++i){
			for(int j=0;j<c;++j){
				if(a[i][j]==-1)
					b[i][j]=-1;
				else{
					int ak=a[i][j]/k;
					if(i+1<r&&a[i+1][j]!=-1){
						b[i+1][j]+=ak;
						b[i][j]-=ak;
					}
					if(i>0&&a[i-1][j]!=-1){
						b[i-1][j]+=ak;
						b[i][j]-=ak;
					}
					if(j+1<c&&a[i][j+1]!=-1){
						b[i][j+1]+=ak;
						b[i][j]-=ak;
					}
					if(j>0&&a[i][j-1]!=-1){
						b[i][j-1]+=ak;
						b[i][j]-=ak;
					}
				}
			}
		}
		for(int i=0;i<r;++i){
			for(int j=0;j<c;++j){
				if(a[i][j]!=-1)a[i][j]+=b[i][j];
				b[i][j]=0;
			}
		}
	}
	int ans1=0,ans2=100000;
	for(int i=0;i<r;++i)
		for(int j=0;j<c;++j)
			if(a[i][j]!=-1){
				ans1=max(ans1,a[i][j]);
				ans2=min(ans2,a[i][j]);
			}
	cout << ans2 << "\n" << ans1;
}

Discussion