2 1 1 3 1 2 3
-1 3
刚开始接触这道题的时候感觉无从下手,不过仔细分析了一下,发现有几点地方要注意:
1.箱子数目一定是大于等于3的,因为1*2+1=3,不然的话一次也不能取,金币永远也取不完了!
2.箱子数目一定不能为偶数,因为如果这样的话,最后一个箱子一定取不到,比如说n = 4,则x最大只能取1,4号箱子一定取不到!
3.要注意题目的关键所在,即对于每只箱子来说至少要取箱子里的金币的数目这么多次数,才能取完该箱子的金币!
我的思路是:将问题一步步缩小,我们发现x=1时,能取到1~3号箱子,x=2时,能取到2~5号箱子,x=3时,能取到3~7号箱子.....
我们发现,每一个x(x>1)相对于前面一个x,这个x总有两个箱子是前面那个x所取不到的,如x=2时,4,5号箱子x=1时取不到,x=3是6,7号箱子x=2取不到,依次类推……
这样的话,我们就发现规律了,如果箱子数为n,假设此时我们能取的最大的数为max,那么n, n - 1,号箱子只有当x取max时才能取到,也就是说,我们至少要取max为n, n - 1号箱子里最大的金币的数目这么多次数,才能将n, n -1号箱子里的金币取完,最重要的是,我们必须要取max这么多次,因为只有取max,我们才能取到n, n - 1号箱子里的金币!
等到n , n - 1号箱子取空之后,我们发现问题的规模变小了n -> n - 2(空箱子可以丢弃了!),然后我们再按照前面的方法再次分析,最终可以将n -> 3,而这种问题已经解答了,即至少要取1, 2, 3号箱子里最多金币数目次数才能取完,至此,题目已经完满解决!
代码如下:
#include <iostream> const int SIZE = 101; using namespace std; int main() { int times; cin >> times; while (times--) { int num, numOfGold[SIZE], tmp, i, j; int max,min; cin >> num; tmp = (num - 1) / 2; /*tmp是能取到的最大的x*/ for (i = 1; i <= num; i++) cin >> numOfGold[i]; /*输入每个箱子金子数目*/ if (num < 3) /*箱子个数至少要为3个,否则一次也不能取*/ { cout << "-1" << endl; } else if ((num & 0x0001) == 0) /*如果箱子比能取到的最大的x的2倍+1还多,说明num号箱子一定取不到*/ { cout << "-1" << endl; } else { min = 0; for (i = num; i >= 5; i -= 2) /*一次一次地将问题的规模缩小*/ { max = numOfGold[i] > numOfGold [i - 1] ? numOfGold[i] : numOfGold[i - 1]; for (j = (i - 1) / 2; j <= i; j++) { numOfGold[j] -= max; if (numOfGold[j] < 0) numOfGold[j] = 0; } min += max; } for (i = 1, max = 0; i <= 3; i++) /*如果只有三个箱子,那么取的次数一定是三个箱子内最多金币的数目*/ { if (numOfGold[i] > max) max = numOfGold[i]; } min += max; cout << min << endl; } } return 0; }