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 }

 

 
posted @ 2015-09-23 23:58  JmingS  阅读(484)  评论(0编辑  收藏  举报