编程题2
编程题2
http://www.nowcoder.com/questionTerminal/43068a1013b4417a85c2c2ce8b18159e
编程题2
题目难度:中等
知识点:数学逻辑,数组
解题思路:
首先,找到初始房间。然后,计算每轮分配情况。最后,计算初始人数。
我们分三种情况来讨论初始房间room_i的位置,其中最后一次被分配的房间为room_x,再分配后房间内最少人数为p_min。
1.room_i在room_x之后。按照每轮分配原则,room_x+1和room_i之间被分配p_min个人,room_i向后绕回room_x的房间则被分配pmin+1个人,可以计算出room_i的初始人数为 p_min×n+[n-(room_i-room_x)]。
2.room_i在room_x之前。同理,room_i+1到room_x之间被分配p_min+1个人,其他房间被分配p_min个人。room_i初始人数为 pmin×n+(room_x-room_i)。
3.room_i和room_x重合。这时重合房间被分配0人,初始人数为 p_min×n。
综合这三种情况,可以发现,不论room_i的位置在哪里,其房间内再分配后的人数总是最少的。如果出现多个房间内人数都与最少人数相同的情况,那么从room_x向前推,第一个人数最少的房间即为room_i。这样我么可以求出room_i的索引了。
随后,根据整数轮次,将每个房间的人数都减去p_min,求出其初始人数。这时只有room_x和room_i重合的情况才会正好分配完,其他情况我们根据最后不足一轮时,两房间之间相隔房间数即可求出room_i初始房间人数。
完整代码如下:
#include <stdio.h> #include<iostream> #include<limits.h> using namespace std; class solution { public: void func() { int n, room_x; cin >> n >> room_x; //输入房间个数n,最后一个被分配的房间room_x room_x = room_x - 1; //room_x的索引-1 long* room = new long[n]; long p_min = INT_MAX; for (int i = 0; i < n; i++) //找到再分配后房间内的最少人数p_min { cin >> room[i]; if (room[i] < p_min) p_min = room[i]; } int room_i = room_x; //从room_x开始往前推room_i的位置 while (room[room_i] != p_min) //根据p_min找到初始房间号room_i room_i = room_i > 0 ? room_i - 1 : n - 1; //room_x之前的第一个最少人数房间就是room_i for (int i = 0; i < n; i++) //所有房间减去p_min人数 room[i] -= p_min; int count = 0; //记录从room_i-1房间到room_x的之间的房间数count for (int i = room_x; i != room_i; i = i > 0 ? i - 1 : n - 1) //当分配不足一轮时 { room[i] -= 1; //从room_x往前减-1 count += 1; } room[room_i] += count + n * p_min; //将多余人数补齐到room_i for (int i = 0; i < n; i++) cout << room[i] << " "; } };