一个算法问题(Google code jam 2011 Arabia 2011)

时间:2011-05-04 22:53:26

标签: algorithm

有一个数字池,它是间隔(0,1)中的任意小数。在游戏的第一轮中,间隔的中间三分之一消失,并且从该池中消除来自该间隔的数字。在接下来的几轮中,每个剩余间隔的中间三分之一消失。在第一轮中,区间[1 / 3,2 / 3]被消除,在第二轮中,两个区间[1 / 9,2 / 9]和[7 / 9,8 / 9]被消除,因此上。还删除了每个删除间隔的端点。

您的角色是按照消除的顺序对数字池进行排序。如果从未消除某些数字,请将它们列在最后。如果出现平局,请先列出较小的数字。

int getRound(double lb, double ub, double val){
double lb2 = (2*lb + ub)/3.0;
double ub2 = (lb +2*ub)/3.0;
if((lb2<=val)&&(val<=ub2)) return 1;
else if (val<lb2){
    return 1+getRound(lb,lb2,val);
}
else return getRound(ub2,ub,val)+1;

}

int main(){
    int N;
    cin >> N;

    vector <pair<int,double> > vp;
    for(int j=0;j<N;j++){           
        double x;
        cin >> x;
        int r = getRound(0,1.0,x);
        //if(r>25) r = 25;
        pair <int,double> pid;
        pid.first = r;
        pid.second = x;
        vp.push_back(pid);
    }
    sort(vp.begin(),vp.end());
    for(int j=0;j<vp.size();j++){
        cout << vp[j].second << endl;
    }
}

让我稍微解释一下上面的代码。 整数 N 是测试数组的长度。

任何人都可以帮我检查上面的代码吗?或者给我一些不符合上述代码的特殊情况?我相信存在一些特殊情况。

谢谢,

1 个答案:

答案 0 :(得分:0)

你的逻辑看起来是正确的,但我担心可能会出现getRound可能进入无限循环的情况。如果ub - lb < 0.1**12,我也会返回1。这将防止浮点错误进入无限循环。但是你有硬编码常数。

我可能会采用val的路径并在每轮中乘以3,然后减去1,然后查看它是否在0 < val < 1范围内。如果你这样做,那么你将要限制你可以去的轮数。这样做的好处是可以避免在除以3时出现舍入误差,这可能导致处理您可以表示的数字时出现逻辑错误。乘以3,唯一可能的逻辑错误是由于生成起始编号的四舍五入。