[英]C++: I don't know how to solve the timeout in the problem of comparing coordinates in the coordinate plane
最多可輸入 100,000 個坐標。 只輸出對應特定條件的坐標。 如果存在x值比每個坐標大而y值小的坐標,則對應的坐標從輸出列表中排除。
我的英語不好,所以我舉了一些例子。
[輸入]首先輸入要輸入的坐標數N。 並輸入坐標。
[輸出]條件對應的坐標編號按升序輸出。
[input example]
6
1 3
6 6
7 3
8 2
8 6
2 1
[output example]
4
5
6
時間限制為 500 毫秒。
[timeout input example]
50000
1 1
1 2
1 3
... skip
1 49999
1 50000
[timeout output example]
1 1
1 2
1 3
... skip
1 49999
1 50000
坐標圖像:
下面的問題用一個簡單的循環就解決了,但是輸入100000個值就會超時。 我不知道該使用哪種算法。
我還附上了我寫的 C++ 源代碼。
另外,我試過用sort函數,但是當N的個數少時,效果很好,當N的個數很大時,就不能正常比較了。 我想我無法正確編寫比較函數。 所以我嘗試在不使用 sort 的情況下編寫源代碼。
想了兩天,改正了,還是沒解決,求幫助。 謝謝閱讀。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
int N;
cin >> N;
bool* visible = new bool[N];
for (int i = 0; i < N; i++)visible[i] = true;
vector<pair<int,pair<int, int>>> v;
for (int i = 0; i < N; i++) {
int a, b;
cin >> a >> b;
v.push_back(make_pair(i,make_pair(a, b)));
}
for (int i = 0; i < v.size(); i++) {
if (visible[i] == false)
continue;
for (int j = 0; j < v.size(); j++) {
if (visible[i] == true &&visible[j]==true && v[i].second.first < v[j].second.first && v[i].second.second > v[j].second.second) {
visible[i] = false;
break;
}
else if (visible[i] == true && visible[j] == true && v[i].second.first > v[j].second.first && v[i].second.second < v[j].second.second) {
visible[j] = false;
continue;
}
}
}
for (int i = 0; i < v.size(); i++) {
if (visible[i] == true)
cout << v[i].first + 1 << endl;
}
return 0;
}
[試圖排序但失敗的源代碼]
#include <iostream>
#include <algorithm>
#include <vector>
#include <tuple>
using namespace std;
bool* visible;
int compare(pair<int, pair<int, int>> n1, pair<int, pair<int, int>> n2) {
pair<int, int> a = n1.second, b = n2.second;
bool swap = false;
if (a.first > b.first && a.second < b.second) {
visible[n2.first - 1] = false;
swap = true;
}
else if (a.first < b.first && a.second > b.second) {
visible[n1.first - 1] = false;
//swap = true;
}
cout << "[" << n1.first << "]" << a.first << ", " << a.second << " vb : " << visible[n1.first - 1] << " :\t[" << n2.first << "]" << b.first << ", " << b.second << "vb : " << visible[n2.first - 1] << "\t";
cout << "swap: " << swap << endl;
return swap;
}
int main() {
int N;
cin >> N;
visible = new bool[N];
for (int i = 0; i < N; i++)visible[i] = true;
vector<pair<int, pair<int, int>>> v;
for (int i = 0; i < N; i++) {
int a, b;
cin >> a >> b;
v.push_back(make_pair(i+1, make_pair(a, b)));
}
sort(v.begin(), v.end(), compare);
for (int i = 0; i < v.size(); i++)
cout << "p" << v[i].first << " : " << v[i].second.first << ", " << v[i].second.second <<"\t"<< visible[v[i].first-1]<< endl;
return 0;
}
在這種情況下,p4 移動到 (4,2)。 在這種情況下,p3,4,5,6 成為正確答案。
我不完全確定這適用於每個角落情況,但這個想法就在這里。 我花了一段時間才確定下來,可能是因為問題描述不是很清楚。 基本上,您希望將可以找到另一個具有較大 x 和較小 y 的點標記為不可見,即在其右下方有另一個點的點。
如果您在 x 上對您的點進行排序,那么您只需要檢查那些具有較大索引的點。
事實上,我們只對 y 最小的那個感興趣,因為它會支配所有其他的。
該值只能在從右向左移動時減小,因此我們只需要跟蹤最小值 y。 唯一的問題是如何處理具有相同 x 的點,因為它們可能在較高的 y 之前具有較低的 y,從而使有效點不可見。 訣竅是確保從右到左瀏覽時(從高索引到低索引),y 會減小。 所以在排序時,如果 x 相等,我們將在 y 上排序。
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
struct point {
int x, y;
bool visible = true;
};
size_t N;
std::cin >> N;
std::vector<point> v(N);
std::vector<size_t> idx(N);
for (size_t i = 0; i < N; ++i) {
auto& p = v[i];
idx[i] = i;
std::cin >> p.x >> p.y;
}
sort(idx.begin(), idx.end(), [&v](const size_t& a, const size_t& b) {
if (v[a].x == v[b].x)
return v[a].y < v[b].y;
return v[a].x < v[b].x;
});
int miny = INT_MAX;
for (size_t i = N; i-- > 0;) {
auto& p = v[idx[i]];
miny = std::min(miny, p.y);
if (p.y > miny) {
p.visible = false;
}
}
for (size_t i = 0; i < N; ++i) {
auto& p = v[i];
if (p.visible) {
std::cout << i + 1 << '\n';
}
}
return 0;
}
我從您的代碼中了解到兩件事,因此我將列出兩個解決方案:
I:這是修改后的“最長遞增子序列”的基本示例。
讓我們首先將坐標視為不同的東西,比方說,坐標 (x,y) 將成為具有高度 (x) 和寬度 (y) 的 ractangle(考慮這就像我們正在制作帶有角 (0,0) 的矩形) (x,0) (0,y) (x,y))。
如果我們需要“上升”點,則意味着它們的區域重疊。 更正式地說,如果我們需要的點列表是 A(1),A(2),A(3),...,A(k),那么對於范圍 1..k-1 中的每個 i,A( i).x<A(i+1).x 和 A(i).y<A(i+1).y。
您可以使用此找到最佳解決方案
注意:坐標應該排序。 根據什么標准? 好吧,只要在對該標准進行排序之后出現最長的遞增子序列,那么它就是正確的。
II:這是找到凸包的基本示例。
多邊形的凸包將是凸多邊形(具有最多節點),其坐標集包含在原始多邊形的坐標集中。 我建議閱讀此內容。 找到上半部分后,你可以應用前面例子中描述的思路,盡管你必須找到一個子串而不是一個子序列,這樣會使復雜度 O(nlog+n)
希望這有幫助
給定兩點 A 和 B,有三種可能的配置:
點之間的“不可見”關系不是std::sort
要求的嚴格弱std::sort
,因此使用實現此關系的比較函數調用std::sort
是未定義的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.