1. 程式人生 > >貪心基礎題(區間排程問題+POJ_3617+POJ_3069)

貪心基礎題(區間排程問題+POJ_3617+POJ_3069)

貪心法就是遵循某種規則,不斷貪心地選取當前最優策略的演算法設計方法.(貪心法和動態規劃的區別)

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;
}