[wikioi]均分纸牌

时间:2022-06-08 02:47:29

这是一道归为贪心题。。。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;
}