C# 谷歌代码Jam 2013 R1B-钻石掉落
昨天“密码堵塞”有一个题为“掉落的钻石”的问题。可以找到全文,但总结如下:C# 谷歌代码Jam 2013 R1B-钻石掉落,c#,algorithm,C#,Algorithm,昨天“密码堵塞”有一个题为“掉落的钻石”的问题。可以找到全文,但总结如下: 钻石沿Y轴下落 如果一颗钻石与另一颗钻石点对点碰撞,则它有50/50的几率向右或向左滑动,前提是它没有被阻止这样做 如果阻止钻石向一个方向滑动,它将始终向另一个方向滑动 如果钻石在两个方向都被阻挡,它将停止并停留在阻挡钻石上 如果一颗钻石落到地上,它会把自己埋到一半,然后停下来 钻石的方向永远不会改变,即它会滑动或下沉,但不会翻滚 目标是找出一颗钻石停在给定坐标上的概率,假设N颗钻石落下 上述要求基本上可以归结为钻石
- 钻石沿Y轴下落李>
- 如果一颗钻石与另一颗钻石点对点碰撞,则它有50/50的几率向右或向左滑动,前提是它没有被阻止这样做李>
- 如果阻止钻石向一个方向滑动,它将始终向另一个方向滑动
- 如果钻石在两个方向都被阻挡,它将停止并停留在阻挡钻石上李>
- 如果一颗钻石落到地上,它会把自己埋到一半,然后停下来李>
- 钻石的方向永远不会改变,即它会滑动或下沉,但不会翻滚李>
- 目标是找出一颗钻石停在给定坐标上的概率,假设N颗钻石落下
受保护字符串解算(字符串行)
{
string[]Inputs=Line.Split();
int N=int.Parse(输入[0]);
int X=int.Parse(输入[1]);
int Y=int.Parse(输入[2]);
int AbsX=X>=0?X:-X;
int SlideCount=AbsX+Y;//必须堆叠在所需层的一侧,以迫使其余水滴向另一侧滑动的数字。
int LayerCount=(SlideCount>1;//该层从零开始的索引是幻灯片计数的1/2
int TOTALLAYREMPTY=((图层*图层)=目标覆盖)
{//如果我们有足够的空投来保证目标被覆盖,概率是1
返回“1.0”;
}
else if(LayerDropsSlideCount?LayerDrops-SlideCount:0;//保证每边都有这么多
int CriticalDrops=LayerDrops-(BalancedDrops您的假设过于简单。您可以下载与我的解决方案相关的大型数据集的正确答案:
你必须计算所有可能占据你兴趣点的钻石组合。为此,我使用了以下公式:
你基本上必须:
- 计算金字塔的高度(即计算固定菱形)
- 计算可以在左侧或右侧自由移动的钻石数
- 计算概率(二项系数之和)
对于后者和点Y,你可以应用这个公式来计算概率
如果您无法解决此问题,也不要担心,因为它非常困难。如果您想要我的PHP解决方案,请参阅:
请注意,如果点位于的固定棱锥内或固定棱锥外,则必须进行计算,还必须进行其他次要检查
<?php
set_time_limit(0);
$data = file('2bl.in',FILE_IGNORE_NEW_LINES);
$number = array_shift($data);
for( $i=0;$i<$number;$i++ ) {
$firstLine = array_shift($data);
$firstLine = explode(' ',$firstLine);
$s = $firstLine[0];
$x = $firstLine[1];
$y = $firstLine[2];
$s = calcCase( $s,$x,$y );
appendResult($i+1,$s);
}
function calcCase($s,$x,$y) {
echo "S: [$s] P($x,$y)\n<br>";
$realH = round(calcH($s),1);
echo "RealHeight [$realH] ";
$h = floor($realH);
if (isEven($h))
$h--;
$exactDiamonds = progression($h);
movableDiamonds($s,$h,$exactDiamonds,$movableDiamonds,$unfullyLevel);
$widthLevelPoint = $h-$y;
$spacesX = abs($x) - $widthLevelPoint;
$isFull = (int)isFull($s,$exactDiamonds);
echo "Diamonds: [$s], isFull [$isFull], Height: [$h], exactDiamonds [$exactDiamonds], movableDiamonds [$movableDiamonds], unfullyLevel [$unfullyLevel] <br>
widthlevel [$widthLevelPoint],
distance from pyramid (horizontal) [$spacesX]<br> ";
if ($spacesX>1)
return '0.0';
$pointHeight = $y+1;
if ($x==0 && $pointHeight > $h) {
return '0.0';
}
if ($movableDiamonds==0) {
echo 'Fixed pyramid';
if ( $y<=$h && abs($x) <= $widthLevelPoint )
return '1.0';
else
return '0.0';
}
if ( !$isFull ) {
echo "Pyramid Not Full ";
if ($spacesX>0)
return '0.0';
if ($unfullyLevel == $widthLevelPoint)
return '0.5';
else if ($unfullyLevel > $widthLevelPoint)
return '0.0';
else
return '1.0';
}
echo "Pyramid full";
if ($spacesX<=0)
return '1.0';
if ($movableDiamonds==0)
return '0.0';
if ( $movableDiamonds > ($h+1) ) {
$otherDiamonds = $movableDiamonds - ($h+1);
if ( $otherDiamonds - $pointHeight >= 0 ) {
return '1.0';
}
}
$totalWays = totalWays($movableDiamonds);
$goodWays = goodWays($pointHeight,$movableDiamonds,$totalWays);
echo "<br>GoodWays: [$goodWays], totalWays: [$totalWays]<br>";
return sprintf("%1.7f",$goodWays / $totalWays);
}
function goodWays($pointHeight,$movableDiamonds,$totalWays) {
echo "<br>Altezza punto [$pointHeight] ";
if ($pointHeight>$movableDiamonds)
return 0;
if ( $pointHeight == $movableDiamonds )
return 1;
$good = sumsOfBinomial( $movableDiamonds, $pointHeight );
return $good;
}
function totalWays($diamonds) {
return pow(2,$diamonds);
}
function sumsOfBinomial( $n, $k ) {
$sum = 1; //> Last element (n;n)
for($i=$k;$i<($n);$i++) {
$bc = binomial_coeff($n,$i);
//echo "<br>Binomial Coeff ($n;$i): [$bc] ";
$sum += $bc;
}
return $sum;
}
// calculate binomial coefficient
function binomial_coeff($n, $k) {
$j = $res = 1;
if($k < 0 || $k > $n)
return 0;
if(($n - $k) < $k)
$k = $n - $k;
while($j <= $k) {
$res = bcmul($res, $n--);
$res = bcdiv($res, $j++);
}
return $res;
}
function isEven($n) {
return !($n&1);
}
function isFull($s,$exact) {
return ($exact <= $s);
}
function movableDiamonds($s,$h,$exact,&$movableDiamonds,&$level) {
$baseWidth = $h;
$level=$baseWidth;
//> Full pyramid
if ( isFull($s,$exact) ) {
$movableDiamonds = ( $s-$exact );
return;
}
$movableDiamonds = $s;
while( $level ) {
//echo "<br> movable [$movableDiamonds] removing [$level] <br>" ;
if ($level > $movableDiamonds)
break;
$movableDiamonds = $movableDiamonds-$level;
$level--;
if ($movableDiamonds<=0)
break;
}
return $movableDiamonds;
}
function progression($n) {
return (1/2 * $n *(1+$n) );
}
function calcH($s) {
if ($s<=3)
return 1;
$sqrt = sqrt(1+(4*2*$s));
//echo "Sqrt: [$sqrt] ";
return ( $sqrt-1 ) / 2;
}
function appendResult($caseNumber,$string) {
static $first = true;
//> Cleaning file
if ($first) {
file_put_contents('result.out','');
$first=false;
}
$to = "Case #{$caseNumber}: {$string}";
file_put_contents( 'result.out' ,$to."\n",FILE_APPEND);
echo $to.'<br>';
}
您的假设过于简单。您可以下载与我的解决方案相关的大型数据集的正确答案:
你必须计算所有可能占据你兴趣点的钻石组合。为此,我使用了以下公式:
你基本上必须:
- 计算金字塔的高度(即计算固定菱形)
- 计算可以在左侧或右侧自由移动的钻石数
- 计算概率(二项系数之和)
用后者和t
<?php
set_time_limit(0);
$data = file('2bl.in',FILE_IGNORE_NEW_LINES);
$number = array_shift($data);
for( $i=0;$i<$number;$i++ ) {
$firstLine = array_shift($data);
$firstLine = explode(' ',$firstLine);
$s = $firstLine[0];
$x = $firstLine[1];
$y = $firstLine[2];
$s = calcCase( $s,$x,$y );
appendResult($i+1,$s);
}
function calcCase($s,$x,$y) {
echo "S: [$s] P($x,$y)\n<br>";
$realH = round(calcH($s),1);
echo "RealHeight [$realH] ";
$h = floor($realH);
if (isEven($h))
$h--;
$exactDiamonds = progression($h);
movableDiamonds($s,$h,$exactDiamonds,$movableDiamonds,$unfullyLevel);
$widthLevelPoint = $h-$y;
$spacesX = abs($x) - $widthLevelPoint;
$isFull = (int)isFull($s,$exactDiamonds);
echo "Diamonds: [$s], isFull [$isFull], Height: [$h], exactDiamonds [$exactDiamonds], movableDiamonds [$movableDiamonds], unfullyLevel [$unfullyLevel] <br>
widthlevel [$widthLevelPoint],
distance from pyramid (horizontal) [$spacesX]<br> ";
if ($spacesX>1)
return '0.0';
$pointHeight = $y+1;
if ($x==0 && $pointHeight > $h) {
return '0.0';
}
if ($movableDiamonds==0) {
echo 'Fixed pyramid';
if ( $y<=$h && abs($x) <= $widthLevelPoint )
return '1.0';
else
return '0.0';
}
if ( !$isFull ) {
echo "Pyramid Not Full ";
if ($spacesX>0)
return '0.0';
if ($unfullyLevel == $widthLevelPoint)
return '0.5';
else if ($unfullyLevel > $widthLevelPoint)
return '0.0';
else
return '1.0';
}
echo "Pyramid full";
if ($spacesX<=0)
return '1.0';
if ($movableDiamonds==0)
return '0.0';
if ( $movableDiamonds > ($h+1) ) {
$otherDiamonds = $movableDiamonds - ($h+1);
if ( $otherDiamonds - $pointHeight >= 0 ) {
return '1.0';
}
}
$totalWays = totalWays($movableDiamonds);
$goodWays = goodWays($pointHeight,$movableDiamonds,$totalWays);
echo "<br>GoodWays: [$goodWays], totalWays: [$totalWays]<br>";
return sprintf("%1.7f",$goodWays / $totalWays);
}
function goodWays($pointHeight,$movableDiamonds,$totalWays) {
echo "<br>Altezza punto [$pointHeight] ";
if ($pointHeight>$movableDiamonds)
return 0;
if ( $pointHeight == $movableDiamonds )
return 1;
$good = sumsOfBinomial( $movableDiamonds, $pointHeight );
return $good;
}
function totalWays($diamonds) {
return pow(2,$diamonds);
}
function sumsOfBinomial( $n, $k ) {
$sum = 1; //> Last element (n;n)
for($i=$k;$i<($n);$i++) {
$bc = binomial_coeff($n,$i);
//echo "<br>Binomial Coeff ($n;$i): [$bc] ";
$sum += $bc;
}
return $sum;
}
// calculate binomial coefficient
function binomial_coeff($n, $k) {
$j = $res = 1;
if($k < 0 || $k > $n)
return 0;
if(($n - $k) < $k)
$k = $n - $k;
while($j <= $k) {
$res = bcmul($res, $n--);
$res = bcdiv($res, $j++);
}
return $res;
}
function isEven($n) {
return !($n&1);
}
function isFull($s,$exact) {
return ($exact <= $s);
}
function movableDiamonds($s,$h,$exact,&$movableDiamonds,&$level) {
$baseWidth = $h;
$level=$baseWidth;
//> Full pyramid
if ( isFull($s,$exact) ) {
$movableDiamonds = ( $s-$exact );
return;
}
$movableDiamonds = $s;
while( $level ) {
//echo "<br> movable [$movableDiamonds] removing [$level] <br>" ;
if ($level > $movableDiamonds)
break;
$movableDiamonds = $movableDiamonds-$level;
$level--;
if ($movableDiamonds<=0)
break;
}
return $movableDiamonds;
}
function progression($n) {
return (1/2 * $n *(1+$n) );
}
function calcH($s) {
if ($s<=3)
return 1;
$sqrt = sqrt(1+(4*2*$s));
//echo "Sqrt: [$sqrt] ";
return ( $sqrt-1 ) / 2;
}
function appendResult($caseNumber,$string) {
static $first = true;
//> Cleaning file
if ($first) {
file_put_contents('result.out','');
$first=false;
}
$to = "Case #{$caseNumber}: {$string}";
file_put_contents( 'result.out' ,$to."\n",FILE_APPEND);
echo $to.'<br>';
}
layer = floor( ( sqrt( 1 + 8 * diamonds ) + 1 ) / 4 )
overflow = diamonds - layer * ( 2 * layer - 1 )
P( nr ) = binomial_coefficient( overflow, k ) * pow( 0.5, overflow )
p = 0.0
for i in range( nr + 1 ):
p += pow( 0.5, overflow - i ) * binomial_coefficient( overflow - i - 1, nr - i )