分数背包的问题

时间:2017-01-18 19:02:23

标签: java algorithm

这是我在Java中实现的代码。 getmax()函数返回最大元素的索引。问题是,我没有得到我的一个测试用例正确。我不知道哪一个,但在线评委给了我以下警告:

  

案例#7/13失败:答案错误   得到:66152.57预计:66152.572    (使用时间:0.19 / 1.50,使用的内存:24469504/671088640。)

public class FractionalKnapsack {
private static double getOptimalValue(int capacity, int[] values, int[] weights) {
    float value = 0;
    //write your code here
    float[] ratio=new float[values.length];
    for(int i=0;i<values.length;i++)
    {
        ratio[i]=(float)values[i]/(float)weights[i];
    }
    int max=0;

    while(capacity>-1)
    {
        max=getMax(ratio);
        if(capacity==0)
        {
            return value;
        }
        if(capacity>0)
        {
            if(weights[max]>=capacity)
            {
                value=value+((float)ratio[max]*(float)(capacity));
                capacity=0;
            }
            else if(capacity>weights[max])
            {
                value=value+(weights[max]*ratio[max]);
                capacity=capacity-weights[max];
            }
            ratio[max]=0;
        }
    }
    return value;
}
private static int getMax(float[] arr)
{
    float max=0;
    int save=0;
    for(int i=0;i<arr.length;i++)
    {
        if(arr[i]>max)
        {
            max=arr[i];
            save=i;
        }
    }
    return save;
}
public static void main(String args[]) {
    Scanner scanner = new Scanner(System.in);
    int n = scanner.nextInt();
    int capacity = scanner.nextInt();
    int[] values = new int[n];
    int[] weights = new int[n];
    for (int i = 0; i < n; i++) {
        values[i] = scanner.nextInt();
        weights[i] = scanner.nextInt();
    }
    DecimalFormat df = new DecimalFormat();
    df.applyPattern(".0000");
    System.out.println(df.format(getOptimalValue(capacity, values, weights)));
}

}

1 个答案:

答案 0 :(得分:1)

您使用的float类型无法区分66152.57(您的输出)和66152.572(所需输出)。例如,您可以在线查看here。参见,尾数只有23位存储,这意味着相对误差可能大约为2 -24 。对于幅度66152.572,它表示绝对误差为0.003943。如果您对原因更感兴趣,请查找一些浮点指南(如this one)。

解决方案是使用double进行浮点计算。 请注意,除非您确实知道float精度足以满足您的应用,否则double几乎总是用于避免此类不幸影响的正确类型。