CODE[VS] 1098 均分纸牌 ( 2002年NOIP全国联赛提高组)
arr[i] :表示每个牌堆的纸牌的数目
平均值 :当纸牌数都一样多时,纸牌的数目
从左向右考虑,每堆纸牌有三种状态:
1) arr[i] == 平均值,考虑arr[i+1]
2) arr[i] < 平均值,此时由arr[i+1]移给arr[i]纸牌。 => 移动纸牌数:(平均值 - arr[i])张
注:
考虑此时,arr[i]缺牌,那么i右边的牌堆必然多牌,无论哪堆多牌,必然有由arr[i+1]将牌移给arr[i]的过程。
3) arr[i] > 平均值,此时由arr[i]移给arr[i+1]纸牌。 => 移动纸牌书:(arr[i] - 平均值)张
注:
考虑此时,arr[i]多牌,那么i右边的牌堆必然缺牌,无论哪堆缺牌,必然有由arr[i]将牌移给arr[i+1]的过程。
每个状态下,所做的动作都是必然需要的,没有做无用功,所以结果最优。
更具体的理解,请点击这里
1 //#define HOME 2 #include <iostream> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cmath> 6 #include <string> 7 #include <algorithm> 8 #include <cstring> 9 #include <set> 10 #include <utility> 11 #include <locale> 12 #include <ctime> 13 using namespace std; 14 const int INF = 0x3f3f3f3f; 15 const int MaxN = 110; 16 17 int N, arr[MaxN], sum; 18 19 void Solve() 20 { 21 int ave = sum / N; 22 int cnt = 0; 23 for (int i = 0; i < N - 1; ++i) 24 { 25 if (arr[i] == ave) continue; 26 if (arr[i] < ave) 27 { 28 arr[i + 1] -= (ave - arr[i]); 29 ++cnt; 30 }else 31 { 32 arr[i + 1] += (arr[i] - ave); 33 ++cnt; 34 } 35 } 36 cout << cnt << endl; 37 } 38 39 int main() 40 { 41 cin >> N; 42 sum = 0; 43 for (int i = 0; i < N; ++i) 44 { 45 cin >> arr[i]; 46 sum += arr[i]; 47 } 48 Solve(); 49 50 51 #ifdef HOME 52 cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl; 53 #endif 54 return 0; 55 }