標題:
202409潛力1-檔案順序files
[打印本頁]
作者:
may
時間:
2024-10-20 15:07
標題:
202409潛力1-檔案順序files
[attach]19996[/attach]
檔案順序 (Files)
問題敘述
在圖形化介面的作業系統中,檔案列出的順序可以由使用者的需求自訂,只要一次點擊就能夠即時地根據某個屬性的數值重新排列不同檔案。常用可排序的屬性包含:檔案名稱、修改時間、檔案類型、檔案大小等,每種屬性支援從小到大或從大到小的排序。
請實作一支程式模擬系統排序若干個檔案數次後的結果。為了方便起見,關於檔案的所有資料都會以正整數的方式呈現,排序時也使用整數的比較方式(而非當成字串使用字典順序比較),也就是在遞增排序時 117 會排在 12 的後面。
假設系統中現在一共有五個檔案,一開始的順序如下表所示:
[attach]19997[/attach]
當使用者第一次點選某個屬性時,會將所有檔案以該屬性升序排列。假設使用者點選了「檔案名稱」時,這些檔案的順序會變成:
[attach]19998[/attach]
接著使用者點選「檔案類型」時,這些檔案就會被用檔案類型升序排列;在依據某條件排序的過程中,若有相同數值則會依照操作之前的順序排列(第一個操作則是根據測資輸入的順序),因此會變成:
[attach]19999[/attach]
當使用者連續點選了某個屬性多次時,會切換該屬性排列的升降序,也就是將升序排列變成降序排列,或者反過來。注意這個改變並不是將順序以完全相反方式呈現,因此其他屬性仍然會保持之前的順序。假設使用者在上一個操作後再次點選了「檔案類型」,也就是連續點選了檔案類型兩次,則這些檔案會被以檔案類型進行降序排列,變成:
[attach]20000[/attach]
輸入格式
第一列有兩個正整數N 與 [attach]20002[/attach],代表檔案的數量以及使用者點選操作的次數。
接下來有 N 列,每一列有四個整數,依序代表該檔案的四個屬性:檔案名稱、修改時間、檔案類型和檔案大小。所有數值介於0到109之間,且保證檔案名稱跟修改時間不會重複。
最後一列有K個整數,代表使用者依序點選了哪一個屬性。屬性只有可能是1代表檔案名稱、2代表修改時間、3代表檔案類型、4代表檔案大小四種。
輸出格式
請輸出N列,每一列4個整數,代表最後一個操作結束後排序完畢的檔案資料。同一列的兩個整數間以一個空白隔開。
[attach]20001[/attach]
輸入範例的說明:
範例 1即是問題敘述內的情形。
在範例2中,一開始點擊三次修改時間後會以修改時間升序排列,檔案名稱的順序會變成 1, 3, 2,接著再點擊四次檔案類型後會以檔案類型降序排列。
評分說明
此題目測資分成五組,每組測資有多筆測試資料,需答對該組所有測試資料才能獲得該組分數,各組詳細限制如下。
第一組(20分):N ≤ 500、K = 1,且檔案類型和檔案大小的數值皆不重複。
第二組(20分):N ≤ 500,且不會連續點擊兩次相同屬性。
第三組(20分):K = 1,且檔案類型和檔案大小的數值皆不重複。
第四組(20分):不會連續點擊兩次相同屬性。
第五組(20分):無特別限制。
https://zerojudge.tw/ShowProblem?problemid=o626
作者:
may
時間:
2024-10-20 21:22
#include <bits/stdc++.h>
using namespace std;
struct File{
int fileInfo[5] = {0};
};
class Cmp{
public:
bool operator() (const File &lhs, const File &rhs)
{
for(auto i: Cmp::sort_order)
{
if(i<0)
{
i *= -1;
if(lhs.fileInfo[i]!=rhs.fileInfo[i])
return lhs.fileInfo[i]>rhs.fileInfo[i];
}
else
{
if(lhs.fileInfo[i]!=rhs.fileInfo[i])
return lhs.fileInfo[i]<rhs.fileInfo[i];
}
}
return false;
}
static vector<int> sort_order;
};
vector<int> Cmp::sort_order;
int main()
{
Cmp::sort_order.clear();
int N, K;
cin >> N >> K;
vector<File> lists(N);
for(int i=0; i<N; ++i)
{
File &f = lists[i];
for(int info=0; info<4; ++info)
cin >> f.fileInfo[info+1];
f.fileInfo[0] = i;
}
vector<int> orders(K);
for(auto &i:orders)
cin >> i;
reverse(orders.begin(), orders.end());
//process click orders
vector<bool> appeared(5, false);
int prev = orders[0], cnt = 1;
for(int i=1; i<orders.size(); ++i)
{
if(orders[i]==prev)cnt += 1;
else
{
if(appeared[prev]==false)
{
appeared[prev] = true;
if(cnt%2==0)prev *= -1;
Cmp::sort_order.push_back(prev);
}
cnt = 1;
}
prev = orders[i];
}
if(appeared[prev]==false)
{
if(cnt%2==0)prev *= -1;
Cmp::sort_order.push_back(prev);
}
Cmp::sort_order.push_back(0);
sort(lists.begin(), lists.end(), Cmp());
for(auto &f: lists)
{
for(int i=1; i<=4; ++i)
{
cout << f.fileInfo[i] << ' ';
}
cout << '\n';
}
return 0;
}
/*
3 7
1 2 5 8
2 4 6 8
3 3 6 7
2 2 2 3 3 3 3
*/
複製代碼
作者:
may
時間:
2024-12-18 11:48
//#include <iostream>
//#include <vector>
//#include <algorithm>
#include <bits/stdc++.h>
using namespace std;
// 定義檔案結構體
struct File {
int name;//檔案名稱
int modified_time;//修改時間
int type;//檔案類型
int size;//檔案大小
int original_index; // 紀錄初始索引,確保穩定排序
};
// 比較函數類別,用來根據指定屬性進行排序
class FileComparator {
private:
int attribute;//屬性
bool ascending;//排序順序
public:
FileComparator(int attr, bool asc) : attribute(attr), ascending(asc) {}//定義排序邏輯,根據傳入的屬性 (attribute) 和排序順序 (ascending) 進行比較
bool operator()(const File a, const File b) {
int valA, valB;
// 根據屬性選擇比較值
switch (attribute) {
case 1: valA = a.name; valB = b.name; break;
case 2: valA = a.modified_time; valB = b.modified_time; break;
case 3: valA = a.type; valB = b.type; break;
case 4: valA = a.size; valB = b.size; break;
default: return false;
}
// 進行升序或降序比較
if (valA != valB)
return ascending ? (valA < valB) : (valA > valB);
// 如果屬性值相同,按原始順序排序
return a.original_index < b.original_index;
}
};
int main() {
int N, K;
cin >> N >> K;
vector<File> files(N);
// 讀入檔案資料
for (int i = 0; i < N; i++) {
cin >> files[i].name >> files[i].modified_time >> files[i].type >> files[i].size;
files[i].original_index = i;
}
vector<int> operations(K);
// 讀入操作資料
for (int i = 0; i < K; i++) {
cin >> operations[i];
}
// 記錄每個屬性目前的升降序狀態,預設為升序
vector<bool> ascending(5, true);
// 按操作順序進行排序
for (int op : operations) {
// 依指定屬性排序
sort(files.begin(), files.end(), FileComparator(op, ascending[op]));
// 切換該屬性的升降序狀態
ascending[op] = !ascending[op];
}
// 輸出結果
for (const auto file : files) {
cout << file.name << " " << file.modified_time << " " << file.type << " " << file.size << endl;
}
return 0;
}
/*
3 7
1 2 5 8
2 4 6 8
3 3 6 7
2 2 2 3 3 3 3
*/
複製代碼
-----------------------------------------------------------------
程式解說
結構體定義:
定義了一個 File 結構體,包含四個屬性(檔案名稱、修改時間、檔案類型、檔案大小)和初始索引 original_index,用來保持穩定排序。
比較器:
使用 FileComparator 類別定義排序邏輯,根據傳入的屬性 (attribute) 和排序順序 (ascending) 進行比較。
如果兩個檔案的指定屬性值相同,會依照初始順序比較(original_index)。
排序操作:
使用 std::sort 函數按照指定屬性進行排序,並在排序完成後切換該屬性的升降序狀態。
主要邏輯:
按輸入順序執行所有的排序操作。
每次操作後更新對應屬性的排序順序。
輸入與輸出:
程式會依照範例輸入進行排序,最後輸出最終排序後的檔案屬性資料。
範例輸入與輸出
輸入:
複製程式碼
5 3
5 10 1 50
1 20 3 30
3 15 2 40
2 25 1 20
4 5 2 10
1 3 3
輸出:
複製程式碼
2 25 1 20
5 10 1 50
3 15 2 40
4 5 2 10
1 20 3 30
重點特性
使用穩定排序來維持原始順序的穩定性。
動態切換升降序狀態,模擬使用者連續點擊的操作。
高效處理多屬性排序問題,適用於實際應用場景。
歡迎光臨 種子論壇 | 高雄市資訊培育協會學員討論區 (http://istak.org.tw/seed/)
Powered by Discuz! 7.2