第一题:
n个人围成一圈,第一个人从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。最后剩下的人为胜者。指定n和m,求胜利者编号。
输入描述:
第一行输入n和m,空格隔开,如10,2
其实就是约瑟夫环
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<assert.h>
#include<cstring>
using namespace std;
int LastRemaining_Solution(int n, int m)
{
int *dp = new int[n+1];
if(n==0||m==0) return -1;
dp[1] = 0;
for(int i=2;i<=n;i++)
dp[i] = (dp[i-1]+m)%i;
return dp[n];
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
printf("%d\n",LastRemaining_Solution(n,m));
}
return 0;
}
第二题:假设有一堆卡片,每张卡片上都有一个字符,我们有一下步骤:
a: 取出最顶上的一张卡片,抛弃
b:如果剩余卡牌数量是偶数,则翻转整沓卡牌
c:把此时最顶上的一张卡牌,放到这沓卡片最后。
一直重复此步骤直到手中没有扑克牌
例如abccd的抛弃顺序为acbdc。
现在给出抛弃序列,求原来的顺序。
解析:
其实就是要找出逆过程即可。
我们倒过来分析,
1:我们最后什么牌都没有,所以第一个逆过程是拿回来一张牌
2:然后执行c的逆过程,把最后一张牌放到最前面面
3:然后执行b的逆过程,如果为偶数,则翻转整沓扑克牌。
然后在拿回一张牌,这样循环往复。
这种数据结构用list正好。
代码:
#include<iostream>
#include<list>
using namespace std;
int main()
{
string input;
while(cin>>input)
{
int len = input.length();
int cnt = 0;
int index = len-1;
list<char> lst;
while(cnt!=len)
{
lst.push_front(input[index]);
++cnt;
if(cnt==len) break;
char ch = lst.back();
lst.pop_back();
lst.push_front(ch);
if(lst.size()%2==0) lst.reverse();
--index;
}
typedef list<char>::iterator Iter;
Iter it = lst.begin();
string ans = "";
while(it != lst.end())
{
ans += *it;
++it;
}
cout << ans <<endl;
}
return 0;
}
第三题:
随着新能源车的普及,网易越来越多的同事开电动车上下班通勤,网易大厦停车场里可以提供使用的电桩数量是s,1<=s<=100,现在有N台电动车等待充电,1<=n<=999,第i台电动车所需要的充电时间为ti, 1<=i<=n,S,N,ti均为正整数。
要求采用最优的算法使得所有同事们在最短的时间内都充好电,并输出所有人都充完电的用时。
输入描述:
输入为2行,第一行N,S,分别为N台电动车和S个电桩,以空格分隔,第二行为每台电动车充电所需的时长为ti,以空格分隔。如:
3 2
2 1 3
输入 6
解析:我觉得可以理解为横坐标为时间,纵坐标为S个充电桩并行给电动车充电。
所以我们可以枚举时间,因为数量级很小,然后s个充电桩并行,比如举个例子。
4 2
8 6 2 3
当然首先得按从大到小的顺序排序。
0时刻,因为有2个充电桩,所以0时刻,8 6可以充电,然后我们将2个充电桩的下一个可以充电的时刻置为8 6,分别设为1,2号充电桩,在我代码中用pre体现,然后对时间进行遍历,那么在6时刻,一辆电动车充电完毕,然后冲时间为3的,那么2号充电桩下一个充电时间点为6+3 =9,那么遍历到8的时候,充电完成,需要时间为2的电动车去充,则1好充电桩下一个时刻冲点时间为8+2=10,这样循环往复,知道n辆电动车全部充满。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAX = 999+10;
int a[MAX];
struct Point
{
int value,index;
}point[MAX];
bool cmp(Point &a,Point &b)
{
return a.value > b.value;
}
int main()
{
int n,s;
int ans[MAX];
int pre[MAX];
while(~scanf("%d%d",&n,&s))
{
memset(pre,-1,sizeof(pre));
int cnt = 0;
for(int i=0;i<n;i++)
{
scanf("%d",&point[cnt].value);
point[cnt].index = i;
++cnt;
}
sort(point,point+cnt,cmp);
int ans1 = -1;
int car_num = 0;
for(int i = 1; i <= 99900;i++)
{
for(int j = 0 ;j < s;j++)
{
if(pre[j]==-1)
{
ans[point[car_num].index] = point[car_num].value;
pre[j] = point[car_num].value;
++car_num;
if(car_num==n)
{
ans1 = max(pre[j],ans1);
break;
}
}
else if(pre[j]==i)
{
ans[point[car_num].index] = pre[j] + point[car_num].value;
pre[j] = pre[j] + point[car_num].value;
++car_num;
if(car_num==n)
{
ans1 = max(pre[j],ans1);
break;
}
}
}
if(car_num==n) break;
}
printf("%d\n",ans1);
for(int i = 0; i<n-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n-1]);
}
return 0;
}
/*
20 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
*/
我这个代码顺便把每个电动车充电等待时间求出来了。