进阶实验2-3.1 海盗分赃 (25分)--递推
解题思路:这道题一直都没想明白要如何求解,后在网上看到这篇大神的文章(见https://blog.csdn.net/fire_for_you/article/details/101981707受益良多,感谢博主分享) ,才知道这道题实际是一道递推题,即要先预测下一次的结果来判断此次分配方案,挺有意思的一道题。
先大概讲下自己的理解:(拿样例来说D=10,P=7)
如若当前是第7号海盗提出分配方案,由于此时船上仅有7号一个海盗,则意味着7号海盗获得全部钻石。
如若当前是第6号海盗提出分配方案,则表明之前5个海盗均已被丢下海,此时船上只剩下6号和7号,又考虑到提出的方案要获得大半数人的同意,此时是要2个人同意,则6号为了活命,只能将所有钻石全部给7号。
如若当前是5号海盗提出分配方案,则表明之前4个海盗均已被丢下海,此时船上只剩下5、6和7号,若5号想要自己得到的钻石最多,则需预测下一轮,即6号提出的方案,如此,可知5号要获得超过半数的支持票(即2个海盗,含5号自己,同意此方案),必须拉拢6号,则5号分配给6号1个钻石即可(因为如果是轮到6号提方案,意味前5个海盗均被丢下海,6号为了保命,一个钻石都得不到)。
如若当前是4号海盗提出分配方案,则表明之前3个海盗均已被被丢下海,此时船上只剩下4、5、6、7号海盗。若4号海盗想要自己得到的钻石最多,则需要预测下一轮,即5号海盗提出的方案,如此,可知,4号要获得超过半数的支持票(即3个海盗,含4号自己,同意此方案),必须拉拢6号和7号,因为根据5号提的方案,选出分配到钻石最少的2个海盗6号和7号(6号仅获得1个钻石,而7号1个钻石都得不到),并在5号提的方案基础上,在给6、7号多分配一个钻石,才能通过4号提出的方案,即4号需要分配6号2个钻石,和7号1个钻石。
如此类推...
方案分配见下表
#include <stdio.h> #include <string.h> #define Max 100+1 int main() { int d,p; scanf("%d %d",&d,&p); int ans[p+1]; memset(ans,0,sizeof(ans)); int pos=p-2;//倒数第3个海盗开始 while(pos!=0) { ans[pos]=d; int cnt=(p-pos+1)/2; int max=0; int i; int flag[p+1]; memset(flag,0,sizeof(flag)); while(cnt!=0) { for(i=pos+1; i<=p; i++) {//寻找下一轮分配到最少钻石的海盗,进行拉拢 if(ans[i]==max&&!flag[i]) { ans[i]++; flag[i]=1; cnt--; } if(!cnt) break; } max++; } for(i=pos+1; i<=p; i++) { if(flag[i]) { ans[pos]-=ans[i]; } else ans[i]=0; } pos--; } printf("%d",ans[1]); return 0; }
另解,还发现个更巧妙的解法(https://blog.csdn.net/TOBEALISTENNER/article/details/79896856?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task)
海盗的人数超过三个人的时候就会出现规律
(1)一个人 分配的结果:D
(2)两个人 分配的结果:0,D
(3)三个人 分配的结果:D-1,1,0
(4)四个人 分配的结果:D-3,0,2,1
(5)六个人 分配的结果:D-4,0,1,2,1,0
(6)七个人 分配的结果:D-4,0,1,2,0,0,1
(7)八个人 分配的结果:D-5,0,1,2,0,1,1,0
(8)九个人 分配的结果:D-5,0,1,2,0,1,0,0,1
(9)十个人 分配的结果:D-6,0,1,2,0,1,0,1,1,0
转化为数学规律 当人数超过三个人的时候 第一个海盗得到的金币为: D - (P / 2 + 1)
然后,代码如此简单!!!泪流满面
#include <stdio.h> int main() { int d,p; scanf("%d %d",&d,&p); if(p==3) printf("%d",d-1); else printf("%d",d-(p/2+1)); return 0; }