1. 程式人生 > 實用技巧 >Clam and fish

Clam and fish

There is a fishing game as following:
  • The game contains n stages, numbered from 1 to n
  • There are four types of stages(numbered from 0 to 3):
    • type 0: There are no fish and no clam in this stage.
    • type 1: There are no fish and one clam in this stage.
    • type 2: There are one fish and no clam in this stage.
    • type 3: There are one fish and one clam in this stage

In each stage,you can do exactly one of the following four actions.

  1. If there is a clam in the stage,you can use this clam to make one pack of fish bait. And the number of packs of fish bait you have is increased by one . You can use this pack of fish bait to catch fish after this stage.
  2. If there is one fish in the stage,you can catch this fish without any fish bait. After this stage,the number of packs of fish bait you have is not changed.
  3. If you have at least one pack of fish bait. You can always catch one fish by using exactly one pack of fish bait even if there are no fish in this stage. After this stage, the number of packs of fish bait you have is decreased by one.
  4. You can do nothing.

Now ,you are given n and the type of each stage. Please calculate the largest number of fish you can get in the fishing game.

輸入描述

The first line contains one integer t(\(1\leq t \leq 2.5\times 10^{5}\)) ---the number of test cases.

There are two lines in each test. The first line contains one integer n (\(1\leq n \leq 2\times 10^{6}\)) . indicating the number of stages in this game. The second line contains a string with length n. The i-th character of this string indicates the type of the i-th stage.

The sum of n across the test cases doesn't exceed 2\(\times\) \(10^{6}\) .

輸出描述

For each test case print exactly one integer -- the maximum number of fish you can catch in the game configuration.

示例1

輸入

2
4
0103
1
1

輸出

2
0

題解

#include<iostream>
#include<cstring>
using namespace std;
char num[2000005];//存放狀態的字串 
int main(){
	int N;//狀態字串的長度 
	scanf("%d",&N);
	while(N--){
		int fish=0;//初始化魚為0 
		int bait=0;//初始化魚餌為0 
		int change=0;//初始化使用魚餌的機會為0 
		int len;
		scanf("%d",&len);
		getchar();//輸入字元時要注意的事項,吞掉回車鍵
		//輸入狀態字串 
		for(int i=0;i<len;++i){
			scanf("%c",&num[i]);
			if(num[i]=='0'||num[i]=='1'){
				change++;
			} 
		}
		//吞掉回車鍵 
		getchar();
		//從頭遍歷狀態字串 
		for(int i=0;i<len;++i){
			//如果有魚,就抓魚 
			if(num[i]=='2'||num[i]=='3'){
				fish++;
			}
			//如果沒魚,並且有蛤蜊,當魚餌數量小於使用魚餌的機會時,
			//把此時的蛤蜊製作成魚餌儲存著,魚餌加1 
			//每經歷一次0或1階段,使用魚餌的機會就減少1 
			else if(num[i]=='1'&&bait<change){
				bait++;
				change--; 
			}
			//其他情況下,只要有魚餌,就使用魚餌
			//使用魚餌後,魚加1,魚餌減1,
			//經歷一次0或1階段後,使用魚餌的機會減1 
			else{
				if(bait>0){
					fish++;
					bait--;
				}
				change--;
			}
		}
		//照此貪心的做法,最後得出的魚的數量就是最大的 
		printf("%d\n",fish);
	}
	return 0;
}

這題我是按貪心的做法來做的,有魚的時候抓魚一定最優,主要就是看沒魚的時候怎麼辦,沒魚的情況分兩種,一種是有蛤蜊,一種是沒蛤蜊,在有蛤蜊的情況下,到底是把當前的蛤蜊抓起來做成魚餌,還是使用揹包裡的魚餌來獲得魚呢?這是需要考慮的,我的做法是提前遍歷一遍狀態字串,來獲得總共有多少次機會能使用魚餌。通過前面的分析,我們發現,只有為0階段或1階段時,我們才可能使用魚餌。所以只要遍歷到0或1階段的狀態,就把使用魚餌的機會加1。

使用魚餌的機會將成為我們決策的重要指標,當我們處於沒魚有蛤蜊的情況下,如果此時揹包裡魚餌的數量小於能使用魚餌的機會的話,我們就把當前池塘裡的蛤蜊製作成魚餌,所以魚餌加1。也就是說,我還有大把的機會能使用魚餌,那我就不在這使用魚餌,而是製作魚餌,這樣魚餌的數量就多了,然後我在後面的機會中使用魚餌,那這就是最優的了。如果此時揹包裡魚餌的數量大於等於使用魚餌的機會的話,那就要馬上使用魚餌了,因為再不使用就沒機會使用了,那樣就會造成浪費了。

當既沒魚也沒魚餌的時候,就只能看當前的揹包裡是否有魚餌可以使用了,如果有那就使用,沒有就什麼也不做。

照著這個貪心的思想來一步步的走,最後得到的魚的數量就是最優的。