【发布时间】:2023-03-19 03:28:02
【问题描述】:
您好,我正在寻找一种算法来解决以下问题:
有 n 个桶和 y 个石头,可以扔进桶里。每个学生在随机桶中扔石头 x 次后,桶的石头数不同。现在教授拿了 100 个便利贴,然后随机把这些便利贴放在桶上。他说:“每个 Post-Id 表示所有桶中石头数量的百分之一,所以如果桶 A 有 10 个 Post-It,如果 Y=100(总石头的数量),它最终可以有 10 个石头。请改变桶中石头的数量,因此每个桶中的石头最多。转移数量最少的团队(参见下面的 TransferAction.class)赢得啤酒!”
这应该是一个常见的分布问题,但我不知道如何解决它。我必须找到一个具有最小更改操作的算法,因此我进行了一些汇总统计,以找出在一些运行/试验/时间中的最佳算法。
谁能帮助或指出最好的算法?
有一些限制:所以不可能把所有的石头放在一个桶里,然后再把适量的石头放回去!最小的意思是,A 桶可以放一些石头到 B 桶里,但是 B 桶不能放石头,那就是 A 桶了。
到目前为止,这是我的代码:
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import org.apache.commons.math3.stat.descriptive.SummaryStatistics;
public class Main {
private static final float Take_Over__Percent_Maximum = 100;
private static Random RANDOM = new Random();
public static void main(String[] args) {
List<Integer> averageSizeList = new ArrayList<Integer>();
int runs = 1000;
for (int i = 0; i < runs ; i++) {
List<TransferAction> transferActions = doSingleRun();
averageSizeList.add( transferActions.size());
System.out.println("The size of transfers:" + transferActions.size());
}
calculateAverage(averageSizeList);
}
private static void calculateAverage(List<Integer> averageSizeList) {
System.out.println();
double[] observed = averageSizeList.stream().mapToDouble(i->i).toArray();
SummaryStatistics sampleStats = new SummaryStatistics();
for (int i = 0; i < observed.length; i++) {
sampleStats.addValue(observed[i]);
}
System.out.println(sampleStats.toString());
}
private static List<TransferAction> doSingleRun() {
// create some buckets
List<Bucket> bucketList = new ArrayList<Bucket>();
int numberOfBuckets = 5;
float percentageOfAllStonesInBucket = Take_Over__Percent_Maximum
/ numberOfBuckets;
for (int i = 0; i < numberOfBuckets; i++) {
Bucket bucket = new Bucket(percentageOfAllStonesInBucket);
bucketList.add(bucket);
}
// now fill buckets with stones
int fillActions = 100;
List<FillAction> fillActionsList = new ArrayList<FillAction>();
for (int i = 0; i < fillActions; i++) {
UUID randomBucketId = bucketList.get(
RANDOM.nextInt(bucketList.size())).getId();
BigDecimal randomAmount = new BigDecimal(RANDOM.nextLong());
FillAction fillAction = new FillAction(randomAmount, randomBucketId);
fillActionsList.add(fillAction);
}
// now try to change the amount of stones in the buckets, so in the end
// every bucket has the right percent of all stones in it
return calculate(bucketList,fillActionsList);
}
private static List<TransferAction> calculate(List<Bucket> bucketList,
List<FillAction> fillActionsList) {
List<TransferAction> transferActions = new ArrayList<TransferAction>();
// the magic should be done here
//...
//...
//now every bucket has maximum percent of all stone or equal stones
return transferActions;
}
}
桶类:
import java.util.UUID;
public class Bucket {
private final UUID id;
private float percentTakeOver;
public Bucket(float percentTakeOver) {
this.id = UUID.randomUUID();
if (percentTakeOver > 100) {
this.percentTakeOver = 100;
} else if (percentTakeOver < 0) {
this.percentTakeOver = 0;
} else {
this.percentTakeOver = percentTakeOver;
}
}
public float getPercentTakeOver() {
return percentTakeOver;
}
public void setPercentTakeOver(float percentTakeOver) {
this.percentTakeOver = percentTakeOver;
}
public UUID getId() {
return id;
}
}
FillAction 类 FillAction 类(最好的算法没有多少 FillAction):
import java.math.BigDecimal;
import java.util.UUID;
public class FillAction {
private final BigDecimal amount;
private final UUID bucketID;
public FillAction(BigDecimal amount, UUID bucketID) {
this.amount = amount;
this.bucketID = bucketID;
}
public BigDecimal getAmount() {
return amount;
}
public UUID getBucketID() {
return bucketID;
}
}
下一步:
import java.math.BigDecimal;
import java.util.UUID;
public class TransferAction {
private final UUID fromBucket;
private final UUID toBucket;
private final BigDecimal amount;
public TransferAction(UUID fromBucket, UUID toBucket, BigDecimal amount) {
this.fromBucket = fromBucket;
this.toBucket = toBucket;
this.amount = amount;
}
public UUID getFromBucket() {
return fromBucket;
}
public UUID getToBucket() {
return toBucket;
}
public BigDecimal getAmount() {
return amount;
}
}
【问题讨论】:
-
能保证每一个百分比都能生产吗?如果 y 是 17(质数)怎么办?
-
是的,为什么不呢。你有 3 个桶 (=x) 和 17 个石头 (=y)。也许桶 A 得到 3 颗石头,B 得到 7 颗石头,C 也得到 7 颗石头。
-
您能否澄清一下:“请更改桶中石块的数量,因此每个桶中的石块最大。最少的团队变化率”?特别是粗体部分。还有,石头怎么搬?从任何桶到任何桶的组?无论移动多少石头和移动多远,这是否被视为一次移动?
-
@aexerus:因为你不能用说 50% 的石头装满一个桶,所以不能准确地达到整数百分比......
-
1.) 如果有 1000 颗石头,而桶 A 有 10% 的可能性,那么 A 可以有 100 颗石头。 2.)变化率意味着=转移到另一个的最小数量的石头。 3.) 可以只从 A 拿 1 块石头到 B,或者你把 100 块石头从 A 转移到 B。距离无关紧要!