经典贪心法:时间序列问题及其全局最优性证明
貪心算法是指在對問題求解時,總做出在當前看來是最好的選擇。也就是說,不從整體上加以考慮,它所作出的僅僅是在某種意義上的局部最優解。一旦貪心算法求出了一個可行解,就要確定這個算法是否找到了最優解。為此,要么證明這個解是最優的,要么說明一個該算法產生非最優解的反例。
為了更方便的說明問題,我們來拿一個實例做分析,下面的題目取自HDU_2037:今年暑假不AC
Problem Description
“今年暑假不AC?” “是的。” “那你干什么呢?” “看世界杯呀,笨蛋!” “@#$%^&*%...”
確實如此,世界杯來了,球迷的節日也來了,估計很多ACMer也會拋開電腦,奔向電視了。 作為球迷,一定想看盡量多的完整的比賽,當然,作為新時代的好青年,你一定還會看一些其它的節目,比如新聞聯播(永遠不要忘記關心國家大事)、非常6+7、超級女生,以及王小丫的《開心辭典》等等,假設你已經知道了所有你喜歡看的電視節目的轉播時間表,你會合理安排嗎?(目標是能看盡量多的完整節目)Input
輸入數據包含多個測試實例,每個測試實例的第一行只有一個整數n(n<=100),表示你喜歡看的節目的總數,然后是n行數據,每行包括兩個數據Ti_s,Ti_e (1<=i<=n),分別表示第i個節目的開始和結束時間,為了簡化問題,每個時間都用一個正整數表示。n=0表示輸入結束,不做處理。Output
對于每個測試實例,輸出能完整看到的電視節目的個數,每個測試實例的輸出占一行。
Sample Input
12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0
Sample Output
5 仔細考察問題(自己舉一些簡單的例子來找規律)后我們發現:在算法的每個階段,都從可以完整收看的節目中選擇一個最早結束的節目觀看。我們將證明在從能看盡量多的完整節目的意義上而言,這種貪心算法是一種最優算法。為了證明該算法的最優性,對變量n應用數學歸納法,其中n是算法中的節目數。設P(n)是命題:如果貪心算法安排了n個節目,那么不可能安排更多的節目。
基礎步驟:設應用上述貪婪算法只安排了1個節目(Ti_s,Ti_e (1<=i<=n),分別表示第i個節目的開始和結束時間),這說明所有其他的節目的開始時間都在安排的那1個節目的結束時間T1_e之前,并且結束時間T1_e <= Ti_e。這又說明了什么?說明任意兩兩節目的播出時間都有重疊,因此如果貪心算法安排了1個節目,那么不可能安排更多的節目。
歸納步驟:歸納步驟是P(k)為真,其中k是一個正整數。也就是說,如果貪心算法安排了k個節目,那么不可能安排更多的節目。下面我們需要證明在k成立的條件下,命題對k+1仍然成立。換句話說,假設貪心算法安排了k+1個節目,那么我們需要證明不能安排更多的節目了。我們以安排盡量多的節目為出發點,那么第一個節目應該是最早結束的那個,因為所有節目的開始和結束時間都已經給定了,因此要想盡可能多的安排節目我們需要在安排了第一個節目后使剩下的時間最大化,即第一個節目是眾多節目中最早結束的那個能保證安排節目的數量達到最大化。剩下的問題就好辦了,剩下的時間安排k個節目已經由我們的歸納假設P(k)保證了。
OK,我們已經完成了基礎步驟和歸納步驟,根據數學歸納法的原理可知:對所有正整數n,P(n)為真。這就完成了最優性的證明。
確定了對于該問題使用貪心法能保證找到一個最優解后,我們可以踏踏實實地編寫程序來實現了:
#include<stdio.h>
#include<string.h>
void bubble_sort(int a[][2], int); // 注意二維數組做形參的寫法
int main(void)
{int n, i, count, first, second;int a[110][2];while(scanf("%d", &n) && n) // n==0,輸入結束
{i = 0;memset(a, 0, sizeof(a));while(n--){scanf("%d%d", &a[i][0], &a[i][1]);i++;}bubble_sort(a, i); // i為數據的個數// 排好序后,從最早結束的開始,找第二早結束的,如果滿足前者結束時間<=后者開始時間,觀看節目數加一,重復上述過程,直至遍歷完所有給出的節目數據。
count = 1;first = 0;second = 1;while(1) {if(a[first][1] <= a[second][0]){count++;first = second;}second++; if(second >= i)break; }printf("%d\n", count);
} return 0;
}void bubble_sort(int a[][2], int n)
{int temp;for(int outer = n-1; outer > 0; outer--)for(int inter = 0; inter < outer; inter++){if(a[inter][1] > a[inter+1][1]){temp = a[inter][1];a[inter][1] = a[inter+1][1];a[inter+1][1] = temp;temp = a[inter][0];a[inter][0] = a[inter+1][0];a[inter+1][0] = temp;}}
} ?
All Rights Reserved. Author:海峰:) Copyright ? xp_jiang. 轉載請標明出處:http://www.cnblogs.com/xpjiang/p/4413903.html
以上.
轉載于:https://www.cnblogs.com/xpjiang/p/4413903.html
總結
以上是生活随笔為你收集整理的经典贪心法:时间序列问题及其全局最优性证明的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 宫颈检查多少钱啊?
- 下一篇: R 语言爬虫 之 cnblog博文爬取