(中石油六)問題 K: 水果傳送(去暴力+找規律)

問題 K: 水果傳送

題目描述
聯歡會開始了,同學們按對應的組別已整齊安靜的就坐。此時小Z發現爲同學們準備的水果還沒有派發。各小組已緊密的連成了一排,於是他想了個辦法,從兩端將水果一個一個傳送給各組,直到滿足各組水果要求個數爲止。假設每秒他只能在兩端各傳送一個水果,求T秒後各組中的水果數。
傳送辦法是:各組拿到水果後都向中間方向的相鄰組傳送(最中間的不用傳),直到相鄰組滿足要求爲止。舉例:小組數M=5,各組要求水果數K=4。
第1秒
在這裏插入圖片描述

輸入
輸入三個正整數,分別是組數M,每組需要的水果數K,時間T,它們的範圍[1…100000]。
數據保證M爲奇數,K爲偶數。T<=M*K/2。
輸出
輸出傳送T秒後,各組別的水果數。
樣例輸入 Copy
5 4 5
樣例輸出 Copy
1 2 4 2 1

先附上我原本錯誤的答案,尾遞歸超時,無腦流,一次一次加。
這裏順便提一下#pragma GCC optimize(2)這個讀入掛,雖然可以在遇到大數據時幫您照樣輸出,但超時依舊,只是幫你檢查一下結果的作用。個人感覺沒什麼大用。

//尾遞歸超時
#include <bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
typedef long long ll;
int m,k,t,a[50002],mid;
void dfs(int n){
	if(n==t){
		for(int i=1;i<=mid;i++){
			if(i==1)	printf("%d",a[i]);
			else	printf(" %d",a[i]);
		}
		for(int i=mid-1;i>0;i--){
			printf(" %d",a[i]);
		}
		return;
	}
	else if(n==0){
		a[1]++;
	}
	else{
		a[1]++;
		for(int i=mid-1;i>0;i--){
			if(a[i]==0)	continue;
			else if(a[i+1]<k){
				a[i]--;
				if(i+1==mid)	a[mid]+=2;
				else	a[i+1]++;
			}
		}
	}
	dfs(n+1);
}
int main(){
	scanf("%d%d%d",&m,&k,&t);
	mid=(m+1)/2;
	dfs(0);
}

很明顯複雜度O(n)=O(x^n),當然尾遞歸(自上而下)也可以改善,降成O(n),比如備忘錄、二分查找、正序(自下而上)等等,但本質和找規律差不多(其實是有點區別的),下面給一種類二分的。
其實這題可以發現左右對稱,只有中間特殊,一遍的規律也很容易找出,所以就分類吧。
將它分成3種情況。
1、還沒到加到中間。
2、到中間了但是中間數沒有超過k值。
3、到中間了且超過k。
PS:這代碼還是小編自己抄別人的,自己實在太懶了。

#include <bits/stdc++.h>
using namespace std;
int a[100001];
int main(){
    int mid,m,k,t,b,c;
    scanf("%d%d%d",&m,&k,&t);
    mid=m/2+1;		//中間數
    c=t-m/2;		//剩下的時間
    b=k/2;			//半對半時間
    
    if(t<mid){			//還沒到mid 
        for(int i=1; i<=t; i++)		a[i]=1;
    }
	else if(t>=mid){
        for(int i=1; i<mid; i++)	a[i]=1;	//初始化 
        if(c*2<=k)		a[mid]=c*2;		//mid還未至K 
        else if(c*2>k){			//mid已至K 
            t=c-k/2;
            a[mid]=k;
            for(int i=mid-1;i>0;i--){
            	if(t==0)	break;
                while(a[i]<k&&t){
                    a[i]++;	t--;
                }
            }
        }
    }
    //輸出 
    for(int i=1;i<=mid;i++){
		if(i==1)	printf("%d",a[i]);
		else	printf(" %d",a[i]);
	}
	for(int i=mid-1;i>0;i--)	printf(" %d",a[i]);
    return 0;
}

發佈了18 篇原創文章 · 獲贊 16 · 訪問量 1344
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章