题意:有n个星球,每个星球有Ai个人,每次有两种选择,第一是从每个星球上去掉1个人,第二个选择是选择一个星球放置一个科学家,将该星球的人数加倍,问最少多少次能够将所有星球上的人数同时变为0,并且如果步数<=1000,还要输出操作顺序。
解法:找出人数最多的那个星球,设最大人数为maxi,那么跑一个循环,每次该星球如果人数<maxi,那么能加倍就加倍到离maxi最近的位置,然后计算他们的差,比如2 1035,加倍后为1024 1035,差为11,那么到时候1024减到11的时候,1035变成了22,那么这个时候马上加倍11,再减即可。每个不等于最大人数的星球上都这样处理即可。predouble[]记录处理前先要加倍到离最大数最近的位置的星球,backdouble[]记录减到差值的时候要加倍的星球。然后输出即可。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define N 100007 int a[N]; int backdouble[5003][2]; int predouble[5004]; int main() { int n,i,j,maxi = 0,kb,kp,ans = 0,flag = 1; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i] == 0) flag = 0; maxi = max(maxi,a[i]); } if(!flag) { puts("0"); return 0; } kb = kp = 0; for(i=1;i<=n;i++) { if(a[i] == maxi) continue; int tmp = a[i]; while(tmp < maxi) { if(maxi+ans <= 1000) //还能输出 { if(2*tmp<=maxi && kp <= 1000) predouble[kp++] = i; else { backdouble[kb][0] = i; backdouble[kb++][1] = 2*(maxi-tmp); } } tmp *= 2; ans++; } } printf("%d\n",maxi+ans); if(ans+maxi > 1000) return 0; for(i=0;i<kp;i++) printf("science mission to the planet %d\n",predouble[i]); for(i=maxi;i>0;i--) { for(j=0;j<kb;j++) if(backdouble[j][1] == i) printf("science mission to the planet %d\n",backdouble[j][0]); puts("flying mission"); } return 0; }