您好我正在搜索算法来解决以下问题:
有n个桶和y石头,可以扔进水桶。在每个学生用随机水桶投掷石头x次后,水桶有不同的石头数。现在教授拿了100张Post-It并随机将这些贴子放在桶上。他说:“每个Post-Id都表示所有水桶中石头数量的百分之一,所以如果水桶A有10个石柱,那么如果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类(最好的算法没有很多FillActions):
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;
}
}
答案 0 :(得分:1)
我不知道你的意思,但我会以我的理解为例,尝试理解你的要求。
可用石头= x15
Buckets = A + B + C
铲斗容量A = 1 / 3~33,33% - >这意味着15 *(1/3)= 5石头
铲斗容量B = 1 / 3~33,33% - >这意味着15 *(1/3)= 5石头
铲斗容量C = 1 / 3~33,33% - >这意味着15 *(1/3)= 5石头
Bucket中的初始石头(符号0):
A=4 | B=8 | C=3
##### | ##### | #####
# 0 # | # 0 # | # 0 #
# 0 # | # 0 # | # 0 #
# 0 # | # 0 # | # 0 #
# 0 # | # 0 # | # #
# # | # 0 # | # #
# # | # 0 # | # #
# # | # 0 # | # #
# # | # 0 # | # #
##### | ##### | #####
<强>予。简易方法算法
想法:想象一下斗圈。
步骤: 1.)取第一个桶,如果达到容量,则取出所有额外的石块并将其放入下一个桶中。然后去下一个桶。
2。)如果达到第二个铲斗容量,则将所有附加钻石放入下一个铲斗。如果没有达到容量。转到下一个桶
...
完成:不容易检查,但是如果你遍历所有桶并且没有达到容量的桶,那么你就完成了。
示例:
步骤1:A中有4颗石头。将4块石头移到B.现在A有0块石头,B有12块石头。
4
A -> B
4 0 12
步骤2:A为空。 B有12块石头。现在将7颗石头从B移到C.B现在有5块石头和10块石头。
4 7
A -> B -> C
4 0 12 5 10
步骤3:A为空。 B有5块石头和10块石头。现在从C到A移动5块石头.C现在有5块石头和5块石头,B还有5块石头。
4 7 5
A -> B -> C -> A
4 0 12 5 10 5 5
移动的石头= 15
交易= ->
符号的3倍
希望您了解我的符号计算方法: - )
<强> II。智能算法
想法:你知道什么桶达到了容量以及什么桶有可用容量。
步骤:
1。)迭代所有桶并记住达到容量和额外石块数量的桶(列表1)。还要记住额外列表中剩余可用容量的桶(列表2)和可用空间量。
2。)迭代列表1并从列表2中取出第一项。然后将所有石头从容器A(从列表1)转移到B(从列表2,B可能达到容量!!!)。然后从A中删除Bucket 1,从B中删除Bucket。
3。)这样做直到一个列表没有任何项目
4.。)进入步骤1并按照步骤2-4进行操作。如果列表1没有任何项目,请完成此操作。
示例:
步骤1:List1 = {B = 3}且List2 = {A = 1,C = 2}。如果你看看下一个算法那么你就知道为什么我记得桶A中的其他石头的值3,以及桶A中的1个缺失的石头或桶B中的2个密苏石!
步骤2:从List1中获取B,从List2中获取A.现在移动3块石头如下。从List1中删除B,从List2中删除A.现在List1为空,所以从步骤1开始。
3
B -> A
8 5 7
步骤1迭代2:List1 = {A = 2}且List2 = {C = 2}。见B不在任何列表中!!!
第2步迭代2:从List2获取A,从List2获取C.现在移动2块石头,如下所示。从List2中删除A,从List2中删除C.现在List1为空,所以从步骤1开始。
3 2
B -> A -> C
8 5 7 5 5
步骤1迭代3:List1 = {}和List2 = {}。看到两个列表都是空的(但重要的只是list1),所以我们完成了!
Moved Stones = 5
交易= ->
符号的2倍
<强> III。更智能的算法
想法:你知道什么桶达到了容量以及什么桶有可用容量。但现在我们记得额外或遗失的石头数量,但请看下面。
示例:
第1步:List1 = {B = 3},List2 = {A = 1,C = 2}
第2步:
1
B -> A
8 5 5
2
B -> C
8 5 5
成品。所有铲斗现在都有5块石头!
Moved Stones = 3
交易= ->
符号的2倍
这是我的帖子的结尾
也许有更好的算法,但我不知道它们的名字,我不想写更多的解释。但我希望我能给你一些可能的实施方法。
也许其他人可以按名称命名一些算法!