3. Project Euler15 給定一個20*20的方格,從左上角到右下角的路徑有多少條?(只允許向右和向下走)
【微--策--略】
1. 五個洞排成一排,其中一個洞裡藏有一隻狐狸。每個夜晚,狐狸都會跳到一個相鄰的洞裡;每個白天,你都只允許檢查其中一個洞。怎樣才能保證狐狸最終會被抓住?
解答:有個問題 錯了 下面是少一天的推理 第一天2洞 第二天2洞 都沒有的話 證明它在後三個裡面 第三天4洞 第四天4洞 都沒有的話 證明第三天的時候 它在3號洞 第四天去了2號洞 第五天3洞 它如果不在 它肯定在1號洞 第六天在2號洞抓到它 bingo?
2. 5個海盜分100個金幣問題
首先從5號海盜開始,因為他是最安全的,沒有被扔下大海的風險,因此他的策略也最為簡單,即最好前面的人全都死光光,那麼他就可以獨得這100枚金幣了。 接下來看4號,他的生存機會完全取決於前面還有人存活著,因為如果1號到3號的海盜全都餵了鯊魚,那麼在只剩4號與5號的情況下,不管4號提出怎樣的分配方案,5號一定都會投反對票來讓4號去喂鯊魚,以獨吞全部的金幣。哪怕4號為了保命而討好5號,提出(0,100)這樣的方案讓5號獨佔金幣,但是5號還有可能覺得留著4號有危險,而投票反對以讓其喂鯊魚。因此理性的4號是不應該冒這樣的風險,把存活的希望寄託在5號的隨機選擇上的,他惟有支援3號才能絕對保證自身的性命。 再來看3號,他經過上述的邏輯推理之後,就會提出(100,0,0)這樣的分配方案,因為他知道4號哪怕一無所獲,也還是會無條件的支援他而投贊成票的,那麼再加上自己的1票就可以使他穩獲這100金幣了。 但是,2號也經過推理得知了3號的分配方案,那麼他就會提出(98,0,1,1)的方案。因為這個方案相對於3號的分配方案,4號和5號至少可以獲得1枚金幣,理性的4號和5號自然會覺得此方案對他們來說更有利而支援2號,不希望2號出局而由3號來進行分配。這樣,2號就可以屁顛屁顛的拿走98枚金幣了。 不幸的是,1號海盜更不是省油的燈,經過一番推理之後也洞悉了2號的分配方案。他將採取的策略是放棄2號,而給3號1枚金幣,同時給4號或5號2枚金幣,即提出(97,0,1,2,0)或(97,0,1,0,2)的分配方案。由於1號的分配方案對於3號與4號或5號來說,相比2號的方案可以獲得更多的利益,那麼他們將會投票支援1號,再加上1號自身的1票,97枚金幣就可輕鬆落入1號的腰包
3. Project Euler15 給定一個20*20的方格,從左上角到右下角的路徑有多少條?(只允許向右和向下走)
首先我們來討論一下2*2方格的情況:
從結點1到結點9的走法:
1-2-3-6-9
1-2-5-6-9
1-2-5-8-9
1-4-7-8-9
1-4-5-6-9
1-4-5-8-9
共有6種不同的走法,仔細的讀者會發現,在結點3,6,7,8到結點9的通道只有一種,是的,這將會是以後解決問題的關鍵之一。
現在我們將方格數推廣到n,定義f(n,n)為結點(0,0)到結點(n,n)的通道數。
演算法如下:
方法一:遞推法
- 遞推公式為f(n,n)=f(n-1,n)+f(n,n-1);
- 初始化條件:當0 <= i <= n,f(n,i)=1,f(i,n)=1。(初始條件的尋找,還得看讀者的觀察能力了)
方法二:排列組合
- f(n,n)=c(n,n+n),其中c(n,n+n)表示n+n中取n
現在我只研究方法一,實現的程式碼如下:
#include <iostream>
#include <TIME.H>
using namespace std;
#define MAX_X 21
#define MAX_Y 21
/*遞迴*/
_int64 Recursion()
{
_int64 a[MAX_X][MAX_Y] ;
for(int i=0;i<=MAX_X-1;i++)
{
a[MAX_X-1][i]=1;
a[i][MAX_Y-1]=1;
}
for (int j=MAX_X-2;j>=0;--j)
for(int i1=MAX_Y-2;i1>=0;i1--)
a[j][i1]=a[j+1][i1]+a[j][i1+1];
return a[0][0];
}
int main()
{
printf("%I64d",Recursion());
return 0;
}
執行結果:137846528820
演算法,雖不是最好,但只為追求更好,還望不吝賜教!!!
*************************************
4. 在一光滑的平面上 左邊有m個小球以v的速度向右運動 右邊有n個小球以同樣的速度向左運動 球的質量相同 且發生完全彈性碰撞 問共碰撞多少次啊
提問者採納
m*n次(前提是質量相等,否則無解)
左一,右二,撞2次
左二,右二,撞4次
左二,右三,撞6次
。
。
。
左m,右n,撞m*n次
5. 在一光
某同學編了一個ax^2+bx+c=0的程式,任何輸入均有輸出,請設計測試用例!!
設:ax^2 =A;bx=B;c=C; 1.A=0,B=0,C=0; 2.A+B=0,C=0; 3.A+C=0,B=0; 4.C+B=0,A=0; 這個思路看得懂吧?就是按這個思路去設計。
6
ddd
dddddddd
隨筆- 74 文章- 0 評論- 14
【演算法題】rand5()產生rand7()
前兩天,睡覺前,偶爾翻起演算法導論,看到隨機函式這一塊內容,裡面有一個練習題.
5.1-2 描述random(a,b)過程的一種實現,它只調用random(0,1).作為a和b的函式,你的程式的期望執行時間是多少?
注:random(a,b)為產生a,a+1,a+2,...,b的函式發生器,且產生各整數的概率相等,同為1/(b - a + 1).
看到這個題目時,似曾相識,腦海浮現了利用random(0,1)產生0或1,從而組成二進位制數,來完成random(a,b)的實現.但是細想以後,感覺有個問題在腦海中有點不明不白.
執行random(0,1)函式k次,使得2k>=(b-a+1),將得到[0,2k)的整數區間,如何將[0,2k)對映到[a,b]的整數區間,保證產生各整數的概率相等,同為1/(b-a+1).
1.當存在k使得2k=(b-a+1)時,只需將產生的二進位制數與[a,b]整數一一對應,即可滿足概率同為1/(b-a+1)的要求.
例如,random(3,6),k=2. 此時,對應關係可為00~3,01~4,10~5,11~6.產生的概率為1/4.
2.當不存在k使得2k=(b-a+1)時,產生[0,2k)區間整數的概率為1/2k,小於1/(b-a+1).[0,2k)如何對映到[a,b]整數區間.
思路一:擴大[0,2k)區間,使得2k可以被(b-a+1)整除,這樣可以把[0,2k)分成N段時,每一段對應[a,b]裡的一個整數.
但這個思路,是不可行的,因為不存在這樣的k值.要麼2k=(b-a+1),要麼2k>(b-a+1)且不可被(b-a+1)整除.
思路二:參取截斷對映,即 [0,2k) 的前部分對映到[a,b],這樣雖然可以達到產生整數的概率相等,但不等於1/(b-a+1),還有如果產生[0,2k)後部分的值如何處理.
這個思路,是可行的,如果產生後部分的值,就繼續呼叫自身,重新random.從結果輸出分析,最終random(a,b)最終輸出的只有[a,b]裡的整數,而且每個整數的概率相等,因而其產生的概率值是1/(b-a+1).
具體的實現程式碼如下:
int random(int a,int b)
{
int m = 1;
int len = b - a + 1;
int k = 0;
//計算最小的正整數k,使2^k >= len
while(m < len)
{
k++;
m *= 2;
}
m = 0;
for(int i = 0;i < k;i++)
{
m += random(0,1) * (1<<i);
}
if(m + 1 > len)
{
return random(a,b);
}
else
{
return m + a;
}
}
dd
http://www.cnblogs.com/dwdxdy/archive/2012/07/28/2613135.html