贪心算法在“均分纸牌”中的应用
给定一堆牌,牌数总量记作cardCount。然后将这些牌分为n个堆,此时牌数总量cardCount必须是牌堆数n的倍数。求解使得移动最少次数的牌,使得n个堆上的牌的数量相等。
笔者使用的是贪心算法,详情如下:
1.首先求得每堆牌的期望值,也就是总牌数与牌堆数的比值,或称为平均值,记作cardAverage。
2.从第一堆开始比较,如果当前堆的牌数cardCount小于平均值cardAverage,那么可以取当前堆的下一堆中的牌进行“补齐”,也就是说当前堆欠缺的数量为(cardAverage-cardCount),则需要从下一堆中取得(cardAverage-cardCount)张牌进行“补给”;
3.有的时候可能会出现下一堆牌中数量还不足以补给的情况,比如:一共有30张牌,第一堆1张,第二堆3张,第三堆26张。第一堆明显需要(10-1=9)张,但是第二堆只有3张,如果进行强行补给,那么第二堆只会剩余(3-9=-6)张,虽不符合事实,但是告知计算机之后并不影响我们的正常计算,也就是此时第二堆需要(10-(-6)=16)张,只需从第三堆中转移过来即可。
4.同样,有的时候会出现前面一堆中的牌数多于后面的一堆中的牌数,这个时候要用到的解法和前面的补给的办法恰好相反,只是将多余的补充出去到下一堆即可,不再赘述。
下面为本人使用Java代码进行的实现:
package com.Yann;
import java.util.Scanner;
public class HelloWorld {
@SuppressWarnings("resource")
public void helloWorld() {
System.out.println("一共几堆纸牌:");
Scanner in = new Scanner(System.in);
int heapCount;// 设置纸牌的堆数
heapCount = in.nextInt();
System.out.println("请分别输入" + heapCount + "堆纸牌的个数:");
int[] cardArray = new int[heapCount];
for (int i = 0; i < heapCount; i++) {
cardArray[i] = in.nextInt();
}
int cardCount = 0;// 定义纸牌的总张数
for (int i = 0; i < cardArray.length; i++) {
cardCount += cardArray[i];
}
if (cardCount % heapCount != 0) {
System.out.println("牌的总数不是堆数的倍数,请重新输入!");
} else {
int cardAverage = cardCount / heapCount;// 求出每一堆的平均值
for (int i = 0; i < cardArray.length - 1; i++) {
if (cardArray[i] < cardAverage) {
System.out.println((i + 2) + "--->" + (i + 1) + ":" + (cardAverage - cardArray[i]) + "张");
cardArray[i + 1] -= cardAverage - cardArray[i];
cardArray[i] += cardAverage - cardArray[i];
} else {
System.out.println((i + 1) + "--->" + (i + 2) + ":" + (cardArray[i] - cardAverage) + "张");
cardArray[i + 1] += cardArray[i] - cardAverage;
cardArray[i] -= cardAverage - cardArray[i];
}
}
}
}
public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
helloWorld.helloWorld();
}
}