貪心基礎題(區間排程問題+POJ_3617+POJ_3069)
阿新 • • 發佈:2019-02-05
貪心法就是遵循某種規則,不斷貪心地選取當前最優策略的演算法設計方法.(貪心法和動態規劃的區別)
1.區間排程問題
Q:一共有n項工作,每項工作的起始時間分別為s[i],e[i],你可以自主選擇是否參加每項工作,現在希望能夠參加最多的工作(每項工作決定了參加就必須全程參與),先想知道最多能參加多少項工作?
分析:這題的策略為貪心法,那麼應該按照何種規則進行貪心呢?這裡給出了四種貪心策略
(1).每次選取開始時間最早的進行工作
(2).每次選取結束用時最短的進行工作
(3).每次選取最少重疊的進行工作
(4).每次選取結束時間最早的進行工作
通過舉反例可知,123規則都不可行,4可行.因為結束的越早,就能夠留下更多的時間給後面的活動~
程式碼略(就是根據結束時間從小到大對活動進行排序,然後看下一個活動的開始時間是否大於結束時間,是的話就可以參加這個活動)
2.POJ_3617 Best Cow Line
分析:給一個定長為N的字串T,構造一個字串S,長度也為N,構造規則為任意從T的頭或尾取出一個字元(每次取一個),保證最後生成的字串T的字典序最小.
感覺這題就是要處理一個問題--前後兩個字元相等該怎麼搞...如果相同的話一直往中間遍歷,直至遇見不同,此時就輸出大的那邊的字元~然後重複操作.
參考程式碼:
#include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int maxn = 1e3+10; int n; char s[2*maxn]; char t[2*maxn]; int main() { while( ~scanf("%d",&n)) { for( int i = 1; i <= n; i++) { getchar(); scanf("%c",&s[i]); } int cur = 0; int tmp; int l = 1, r = n; while( l <= r) { int flag = 0; for( int i = 0; l+i <= r; i++) { if( s[l+i] < s[r-i]) { flag = 0; break; } else if( s[l+i] > s[r-i]) { flag = 1; break; } } if( !flag) { t[++cur]= s[l++]; } else { t[++cur] = s[r--]; } } for( int i = 1; i <= cur; i++) { printf("%c",t[i]); if( i%80 == 0) putchar(10); } if( cur%80) putchar(10); } return 0; }
3.POJ_3069 Saruman's Army
分析:一共n個點,位置為x[i],可以在點上放置標記,每個標記可以射擊到左右r的距離,問至少放置多少個標誌(標誌必須放在這n個點上),可以讓所有點都能被標記.
參考程式碼:
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int maxn = 1e3+10; int r,n; int x[maxn]; int main() { while( ~scanf("%d%d",&r,&n)) { if( r == -1 || n == -1) return 0; for( int i = 1; i <= n; i++) scanf("%d",&x[i]); sort(x+1,x+1+n); // for( int i = 1; i <= n; i++) // printf("%d ",x[i]); // printf("\n"); int cnt = 0; /*int l = x[1]; for( int i = 2; i <= n; i++) { if( x[i]-l >= r) { cnt++; // printf("*%d\n",x[i-1]); int pos; if( x[i]-l == r) pos = i; else pos = i-1; int flag = 1; for( int j = pos; j <= n; j++) { if( x[j]-x[pos] > r) { l = x[j-1]; flag = 0; break; } } if( flag) break; } }*/ int i = 1; while( i <= n) { int tmp = x[i]; while( i <= n && x[i] <= tmp+r) i++; tmp = x[i-1]; while( i <= n && x[i] <= tmp+r) i++; cnt++; } printf("%d\n",cnt); } return 0; }