題目連接:php
http://acm.hdu.edu.cn/showproblem.php?pid=1538ios
題目類型:ide
模擬spa
題意歸納:.net
有1~n,n個海盜,m塊金子,第n個海盜要提出一個分金方案,若是有一半以上的人贊成,就馬上分金,反之就將這我的扔下水裏,問全部狀況都是最優解的狀況下,要給第p個海盜分多少金?code
解題思路:blog
若是隻有一我的,因此確定是給本身。ip
若是有兩我的,那麼本身將全部的錢都給本身,那麼本身也贊成分配,就能夠獲得一半以上的人的贊成。ci
若是有三我的,第一我的知道若是不一樣意三號,那麼本身絕對分不到錢,因此三號給多少,一號都會贊成,有比沒有強嘛,因此,三號只須要給一號一枚金幣,剩下的全都收到囊中便可。get
若是有四我的,若是第四我的死了,就像上種狀況同樣,因此只須要給二號一枚金幣,就能夠得到一半的支持。
........
以此類推,只要第n個海盜給本身編號奇偶性相同的海盜各一枚金幣,便可。那麼問題就來了...
若是獲得的金子不夠賄賂怎麼辦,也就是m*2<n的狀況下,那就不是錢不錢的問題了,那就是小命要緊了,具體分析一下:
假若有500個海盜,可是隻有100枚金幣,怎麼辦?
對於201號來講,本身不能拿金幣,而且把金幣給除本身以外的其餘奇數號海賊就能存活
對於202號來講,本身一樣不能拿金幣,而且吧金幣給除了本身以外的其餘偶數號海賊就能存活
對於203來講,至少須要102我的的支持,可是本身賄賂的拿金子得到的海盜加上本身,只能拿到101票,因此203必死,
對於204,若是本身死了,203必死,因此203必定會支持本身,因此本身吧金幣分給以前的前200號偶數,一共能夠獲得100+1(203)+1(204),本身能夠保證不死。
對於205號,204,203已經有了保全之策,因此他們是不會支持205的,因此205必死。
金幣數量的不肯定性:由上面的推理可知, 當n=2m+2時, 上一輪推理沒有分到金幣的人的金幣數量首次具備不肯定性, 而且在n>2m+2時, 這種不肯定性必定會延續下去, 輪到由於n號決策者以前的一我的決策時, 那我的確定分不到金幣了, 因此在上一輪推理中沒有分到金幣的人的個數必定大於m。
綜上所述就是該題的解題思路,很是感謝大神的解題思路,給我帶來了太多的靈感,參考連接:
http://blog.csdn.net/acm_cxlove/article/details/7853916#comments
題目:
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 996 Accepted Submission(s): 384
#include<iostream> #include<cstdio> #include<ctime> #include<cstring> #include<cmath> #include<algorithm> #include<cstdlib> #include<vector> #define C 240 #define TIME 10 #define inf 1<<25 #define LL long long using namespace std; //保存2的冪 int fac[15]={2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768}; void slove(int n,int m,int p){ //金幣夠賄賂的狀況 if(n<=2*m){ //不是決策者,並且奇偶性相同,都能被賄賂 if(n!=p&&(n%2==p%2)) printf("1\n"); //剩下的都是決策者擁有 else if(n==p) printf("%d\n",m-(n-1)/2); else //其他人分不到金幣,他們的決策不影響全局 printf("0\n"); return ; } //這時候的不一樣在於決策者不能拿金幣 else if(n==2*m+1){ if(p<2*m&&p&1) printf("1\n"); else printf("0\n"); return ; } int t=n-2*m,i; //這是恰好保命的狀況,對於決策者來講,確定沒有金幣 //對於其它人來講,要麼確定沒有金幣,要麼可能沒有金幣,不肯定性 for( i=0;i<14;i++){ if(t==fac[i]){ printf("0\n"); return; } } for( i=1;i<14;i++) if(t<fac[i]){ //決策者必死 if(p>2*m+fac[i-1]&&p<2*m+fac[i]) printf("Thrown\n"); else printf("0\n"); return ; } } int main(){ int t,n,m,p; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&p); slove(n,m,p); } return 0; }