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 #include3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 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 }else31 {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 HOME52 cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;53 #endif54 return 0;55 }