这是一道归为贪心题。。。http://wikioi.com/problem/1098/ 参考:http://www.cnblogs.com/taoziwel/articles/1859984.html
思路:
1.首先可以想到最终的结果是每一堆牌的数目一样,那么从最大往最小的去补,但这个顺序怎么弄好呢?一时不好想,因为有只能从左右两边补的限制。
2.这个时候想到从最左往右顺着来,一个一个解决了。多了就往右推,少了就从右补,但补的时候可能会出现右边的牌不够的情况。比如1,2,27。
3.这个时候想,先不管三七二十一,往下走吧。那么补完了可能出现负数,但是因为右边的牌肯定够多(否则avg就不是平均数了),“只是交换了移动的顺序而已”。
4.对于这个交换了移动的顺序,我是这么理解的,可以尝试把这个移动顺序算回来,是个递归的算法。那么当所剩牌为正的时候,就会把左边的小的(否则可能负的)先补上。
void CalcMoveOrder(i) { if () // after move, cards[i] > 0 { // save step[i] } else { CalcMoveOrder(i+1); } }
5.再来两个例子用来理解:1,2,27,13,7。这个例子表示中间有可能会出现move完正好是avg的情况。
6. 27,2,1。这个是左边比右边大的情况。
最终的代码:
#include <iostream> using namespace std; int main() { int n; cin >> n; int cards[105]; int sum = 0; for (int i = 0; i < n; i++) { cin >> cards[i]; sum += cards[i]; } int avg = sum / n; int move = 0; for (int i = 0; i < n -1; i++) { if (cards[i] == avg) continue; else { cards[i+1] += (cards[i] - avg); cards[i] = avg; move++; } } cout << move << endl; }