假设一个开关需要a
分钟开启一个灯,它开启b
分钟。目的是在至少1分钟内打开灯并打开灯的顺序以打开,否则应打印-1
。
假设我输入如下:
2
1 5
5 10
第一行是1< = n< = 10 ^ 4的有多少个开关。
第二行是每个开关转动所需的时间 上。
第三行是灯光持续多长时间。
所以一个开关:a = 1,b = 5,另一个开关:a = 5,b = 10
如果我们打开开关1然后打开2,它将看起来像这样:
let turn on time: 0 let on time: 1 011111 0000011111
我们无法满足这个条件。另一方面,如果我们有2然后是1,那么它将是
0000011111 011111
因此灯亮4分钟> 1这样很好,输出是
2 1
其他输入:
2 5 5 5 5
输出:-1
(由于开启时间与其他时间相同)
3 1 4 1 5 3 4
输出:2 1 3
或2 3 1
我的代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
class Switch {
public:
int num;
int turnon;
int time;
Switch(int n) { num = n; turnon = 0; time = 0; }
};
bool comparator(Switch a, Switch b) { return a.turnon > b.turnon; }
int main()
{
int n=0;
cin >> n;
vector<Switch> v;
for(int i=0; i<n; i++) {
Switch s = Switch(i+1);
v.push_back(s);
}
for(int i=0; i<n; i++) {
int a = 0;
cin >> a;
v[i].turnon = a;
}
for(int i=0; i<n; i++) {
int b = 0;
cin >> b;
v[i].time = b;
}
while(v.size() >= 1) {
int maxtimeleft = -2147484637;
int maxindex = 0;
for(int i=0; i<v.size(); i++) {
int time = v[i].time;
for(int j=0; j<v.size(); j++) {
if(j!=i)
time -= v[j].turnon;
}
if(time > maxtimeleft) {
maxtimeleft = time;
maxindex = i;
}
}
if(maxtimeleft < 1) {
cout << "-1";
return 0;
}
cout << v[maxindex].num << endl;
v.erase(v.begin()+maxindex);
}
主要思路:我通过每个开关然后从其“准时”中减去所有其他开关的“开启时间”。我发现开关给了我剩下的最长时间,然后将其打印出来并将其移除,然后重复此操作直到只剩下一个开关。
此代码通过前三个测试,但未通过称为“时间限制错误”的测试。我想这是因为这个算法是一个O(n ^ 3)算法,因为它有两个for
循环,寻找最好的删除开关,并重复它直到没有剩余的开关。关于如何改进这个的任何想法?这是一个家庭作业问题。
答案 0 :(得分:1)
我能想到的最简短的解决方案是:
asymtotic复杂性由排序控制,所以你最终会得到O(n(log(n)))。
根据数字的大小,您可以将空间换成时间,并通过为每分钟分配一个元素的向量并将每个开关直接放在位置,将其转换为一个带有线性的线性复杂度(可能具有高常数)的算法t_i在那个向量中。基本上,您正在创建一个非常稀疏的哈希表。
最后,您可以动态调整粒度,但除非您有非常严格的时间和空间限制,否则我认为没有必要。