#題目:
給定一個值M,和許多不同的線段
求最少的線段可完整覆蓋0到M
#思路:
從零開始要找第一個線段,該線段的左值必須在零的左邊或等於零
在這個條件下再去尋找擁有最大右值的線段,以此類推
這樣便可確保利用最少的線段填滿0到M
*需考慮無法填滿的兩個情況:
1.尋找線段時,找不到左值符合條件的線段
2.已經用完所有線段後,依然無法填滿(亦即,最大右值的線段的右值小於M)
#include <iostream> using namespace std; struct segment{ int l, r; }; int main(int argc, const char * argv[]) { int cases, M; while (cin >> cases) { while (cases--) { segment seg[100005]; segment ans[100005]; cin.get(); //空行 cin >> M; int i = 0; while ((cin >> seg[i].l >> seg[i].r)) { if (seg[i].l == 0 && seg[i].r == 0) break; //結束 else if (seg[i].l < 0 && seg[i].r < 0){ //兩端都小於0 不用考慮 直接設為0 0 seg[i].l = 0; seg[i].r = 0; } i++; } int larger_r = 0, mark = 0, count = 0;
/*用larger_r找有最大r的新片段,mark記錄該片段的index,count計算片段數量*/ int a = 0; ans[a].l = 0; ans[a].r = 0;//ans紀錄每個片段的值 while (larger_r < M && count < i) { for (int j = 0; j < i; j++) { if (seg[j].l <= ans[a].r && seg[j].r > larger_r) {
/*新片段的l要小於等於上一個片段的r,再找最大r*/ larger_r = seg[j].r; mark = j; } } if (larger_r == ans[a].r){ //找不到的情況 表示0到M無法被完整覆蓋 count = 0; break; } else { ans[++a].l = seg[mark].l; ans[a].r = seg[mark].r; count++; } } if (larger_r < M || count == 0) cout << '0' << endl; else { cout << count << endl; for (int i = 1; i <= count; i++) { cout << ans[i].l << " " << ans[i].r << endl; } } cout << "\n"; } } return 0; }
沒有留言:
張貼留言