中级农民
- 积分
- 138
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2016-9-7
- 最后登录
- 1970-1-1
|
第四轮 药片题:药瓶中每一个状态是由w(整片个数), h(半片个数)以及到达该状态的概率p唯一决定的。这样就可以定义一个状态State的struct. 然后根据题意根容易写出状态转移方程:
1. State(w=0,h=0) has no next state;
2. State(w>0,h) changes to State(w-1,h+1) with chance=w/(w+h) and to State(w,h-1) with chance=h/(w+h);
3. State(w=0,h>0) always changes to State(0,h-1) with change=1.
然后用这些 State change就可以模拟每天药瓶状态。
对于求某个状态的概率,可以将每个State看成binary tree的一个node, 每一天的所有可能状态正好是binary tree同一层上的所有nodes, 第k天的状态就在第k层上。用queue做level order traversal到第198层,然后将所有State为w=1,h=0的概率叠加即可(因为tree从root到某一层任意node的path都是互斥时间,所以总概率相加)
- // drug state in the bottle
- struct State {
- int w, h; // number of whole and half pills
- double p; // probability of current state
- State(int whole, int half, double prob):w(whole),h(half),p(prob){}
- };
- class Drug {
- private:
- int w, h, w0; // number of whole, half and initial whole pills
- queue<State> states; // all possible states today
-
- public:
- Drug(int whole):w(whole),h(0),w0(whole) {
- states.emplace(whole, 0, 1.0);
- }
-
- // a random state next day
- void nextDay() {
- if (w + h == 0) return;
- if (rand()%(w+h) < w) { w--; h++; } else h--;
- }
-
- // print current state
- void printState() const {
- cout << "Current number of whole = " << w << ", half = " << h << endl;
- }
-
- // all possible states next day
- void nextDayStates() {
- queue<State> nextstates;
- while (!states.empty()) {
- auto state = states.front(); states.pop();
- int ww = state.w, hh = state.h;
- if (ww + hh == 0) return; // empty bottle
- if (ww) { // whole pill exists
- // pick a whole pill
- nextstates.emplace(ww-1,hh+1, ((double)ww)/(ww+hh));
- // pick a half pill
- if (hh) nextstates.emplace(ww,hh-1, ((double)hh)/(ww+hh));
- }
- // no whole pill, has to pick a half pill
- else nextstates.emplace(0,hh-1, 1.0);
- }
- states.swap(nextstates); // update states for next day
- }
-
- // get probability of a given state
- double getStateProb(int whole, int half) {
- double prob = 0.0;
- if (whole < 0 || half < 0) return prob;
- int nDays = 2*w0 - (2*whole+half); // days elapsed
- if (nDays < 0) return prob;
- queue<State> empty; states.swap(empty);
- states.emplace(w0, 0, 1.0); // reset to initial state
- while (nDays-- > 0) nextDayStates();
- while (!states.empty()) { // combine probability of given states
- auto state = states.front(); states.pop();
- if (state.w == whole && state.h == half) prob += state.p;
- }
- return prob;
- }
- };
复制代码
补充内容 (2016-10-24 14:39):
Typo: "因为tree从root到某一层任意不同的node的path都代表互斥事件,所以总概率相加" |
|