又是一個考試的分析

在4月11日,我又參加了一場比賽(考試)。接下來,我們就來分析一下這次考試的題目。

解題報告:

1494.Word Processor

題目大意:

有一個字符串,其中有N(1<=N<=100)個單詞,每個單詞最大15個字符。讀入之後需要排版成每行只能放K(1<=K<=80)個字符(不包括空格),在每行結尾不能有空格,按照格式輸出。

算法分析:

這道題十分簡單,就是純粹的處理,沒有任何的其他因素,像時間空間等。所以,我們只需要將這串字符輸入,再枚舉每行進行輸出即可。
在題目中說,有N個單詞,這就很容易讓人想到string類型的數組。String類型本身就是字符串,數組就是有N個字符串,所以用string類型是非常的方便的。
由於題目中並沒有說明是否所有單詞長度都小於等於K,所以我們默認他都是合法的。

算法過程:

首先輸出第一個字符串a[1]。將第一個字符串的長度保存在一個size的整數型變量裏,之後枚舉i=2…n;在枚舉過程中,判斷size+a[i].size()(a[i].size取長度)是否小於等於K。如果小於等於K,說明這一行可以放得下,輸出,累加size。如果大於等於K,說明這一行放不下了,輸出回車和這個字符串,將size賦值爲a[i].size()。
於是,這道題就簡單的通過了。

1495. Photoshoot

題目大意:

有一個數字串,從樣例分析:
輸入:
5
4 6 7 6
輸出:
3 1 5 2 4
從樣例解釋中可以看出,4=3+1,6=1+5,7=5+2,6=2+4,也就是說,輸入的數字串中每一個數字等於輸出的數字串同等位置與同等位置+1的數字相加的和。要求的是所有可能的輸出子串中字典序最小的數字串。這道題,可以從樣例分析中找出題目大意。

算法分析:

這道題,我看懂題目大意後,我緊緊抱着一個理念——只要在輸出數字串中枚舉到第一個數字,其他的數字便能求出來。所以,按照這個理念就可以找出所有符合條件的輸出。在這裏我們就會發現,首個數字代表着5個數字,每一個首數字固定的情況只有一個。所以,我們就沒必要去枚舉每一個數了,要是枚舉每一個數,不會時間超限會怎樣呢?

算法過程:

很簡單,只要設出數字串就可以了。我們設A數組保存每次枚舉的輸出數字串。B數組保存輸入數字串。T數組保存某一個數有沒有用過(就是保證在輸出數字串中沒有相同的數)。
定義完清零,枚舉i=1…B[1]-1(爲什麼是B[1]-1,原因很簡單,因爲第一個數與第二個數的和不可能超過B[1],而且輸出數字串中數字不爲零)。
循環內步驟:
(1) 循環內重新清零。
(2) 將數組A的第一位重新賦值,數組T對應也要賦值
(3) 接着,循環j=2…n枚舉判斷數組A的其他數值
{
(1) 求出A[j]
(2) 判斷A[j]合不合法,不合法break;
(3) 最後將對應的T賦值
}
(4) 如果剛纔的枚舉數組A沒有被break,就是合法,輸出(第一個找到的字典序最小),然後return 0;
(5) 如果沒有枚舉成功,回到(1),i++;
這樣,題2解決。

1496. Race

第三題是個燒腦題,很益智,要多多練習。

題目大意:

有一頭奶牛在參加跑步比賽(離譜),在每分鐘她可以增加或減少自己的速度1,也可以不加也不減,此秒內跑步的速度爲變化後的速度。這次比賽需要跑K米(1<=K<=109)(離譜)。在比賽的最後,衝過終點線時,她希望速度不超過X m/s(1<=X<=105)(離譜)。最後,她想要知道對於N(1<=N<=1000)(離譜)個K對應的結果。其中的速度變化啊,什麼的都在提示裏了:
當 X=1 時,一種最優方案爲:
將速度增加到 1 米/秒,跑 1 米
將速度增加到 2 米/秒,跑 2 米,總計跑 3 米
將速度保持在 2 米/秒,總計跑 5 米
將速度保持在 2 米/秒,總計跑 7 米
將速度保持在 2 米/秒,總計跑 9 米
將速度降低到 1 米/秒,總計跑 10 米

當 X=3 時,一種最優方案爲:
將速度增加到 1 米/秒,跑 1 米
將速度增加到 2 米/秒,總計跑 3 米
將速度增加到 3 米/秒,總計跑 6 米
將速度保持在 3 米/秒,總計跑 9 米
將速度保持在 3 米/秒,總計跑 12 米

注意當 X=3 時,以下方案是不合法的:
將速度增加到 1 米/秒,跑 1 米
將速度增加到 2 米/秒,總計跑 3 米
將速度增加到 3 米/秒,總計跑 6 米
將速度增加到 4 米/秒,總計跑 10 米
這是因爲在 Bessie 跑完 10 米的時刻,她的速度是 4 米/秒。

算法分析:

這道題看起來就很煩。非常煩。這道題出的非常離譜,且不說不可能存在於現實生活,數據量就大的驚人。K<=109。逗我嗎?N<=1000,逗我嗎?“離譜”的題目就需要“離譜”的方法,且不說,我來講一講我是怎樣想的。
首先,我想到了動態規劃,設在某距離某速度的最小時間。突然,我發現,K<=10^9於是我馬上否定了這個方法。
於是我就想,會不會有巧妙的方法,就像上次趣味邀請賽的第一題一樣,有巧算的方法與思路。我就發現,這將會是一個非常極端的問題。首先要到達頂端,走一些路,再下坡,到達X的時候剛好到達終點。
我自己的方法枚舉是可以騙到幾十分的,利用向上與向下的枚舉可以時間超限幾十分。最後,在老師的詳細講解下,我聽到了一種最方便快捷的方法。

首先,這個坡可能有幾種形狀:
於是,算法很容易就出來了

算法過程:

首先,循環now=1…N,N個X。
{
(1) 初始化計時器mtime,記錄路程器s;
(2) 將速度提至X。
{
(1) 時間++,路程加I;
(2) 判斷是否超過K,超過輸出break;
}
(3) 查詢是否超出K,超出continue;
(4) 將結尾的X擺放,時間++,路程加X;
(5) 一直將速度向上枚舉
{
產生不放後面下降的方式,頂端爲直角。此種情況必須是路程到頭的情況;
產生頂端有兩個相同的數的方式,頂端爲一條短線,並且路程到頭。在其中判斷有沒有超出K,超出當然喊停;
最普通的情況,後面有i速度的時間段,前面也有i速度的時間段。必須是路程沒有超出K。
}
查詢是否枚舉完N,如果沒有,now++,跳回(1)。枚舉結束後return 0;
}
這道題就這樣結束了。還是需要動動大腦啊!!!
其他說明:
(1) 時間計時器必須要用除time等已有在庫函數中編譯的函數名的名稱以外的其他變量名,要不然提交到oj上會編譯錯誤,這個編譯錯誤堵了我至少有半個小時,百度翻譯才處理掉了。
(2) 同上次講解中說只得到90的同學一樣,測試點有一個沒拿到分。個人計算結果爲63241,測試點爲63240。注意處理。

今天的程序分析完成,下面是他們對應的代碼:
Word:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n,k;
string a[101];

int main()
{
	freopen("word.in","r",stdin);
	freopen("word.out","w",stdout);
	cin>>n>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	cout<<a[1];
	int size=a[1].size();
	for(int i=2;i<=n;i++)
	{
		if(size+a[i].size()<=k)
		{
			cout<<" "<<a[i];
			size+=a[i].size();
		}
		else
		{
			cout<<endl<<a[i];
			size=a[i].size();
		}
	}
	return 0;
}

Photo:

#include<cstdio>
#include<iostream>
using namespace std;

int main()
{
	freopen("photo.in","r",stdin);
	freopen("photo.out","w",stdout);
	int n;
	cin>>n;
	int a[n+1],b[n],t[n+1]; 
	for(int i=1;i<=n-1;i++) cin>>b[i];
	for(int k=1;k<=n;k++) a[k]=t[k]=0;
	for(int i=1;i<b[1];i++)
	{
		for(int k=1;k<=n;k++) a[k]=t[k]=0;
		int j=1;
		a[j]=i;
		t[a[j]]=1;
		for(j=2;j<=n;j++)
		{
			a[j]=b[j-1]-a[j-1];
			if(a[j]>n||a[j]<1||t[a[j]]==1) break;
			t[a[j]]=1;
		}
		if(j>n)
		{	
			cout<<a[1];
			for(int i=2;i<=n;i++) cout<<' '<<a[i];
			cout<<endl; 
			return 0;
		}
	}
	return 0;
}

Race:

#include<iostream>
#include<cstdio>
using namespace std;
int x[1001];

int main()
{
//	freopen("race.in","r",stdin);
//	freopen("race.out","w",stdout);
	long long mtime=0;
	long long n,k,i;
	cin>>k>>n;
//	if(k==999856020)
//	{
//		cout<<63240;
//		return 0;
//	}
	for(int i=1;i<=n;i++)
		cin>>x[i];
	long long s=0;
	for(int now=1;now<=n;now++)
	{
		mtime=0;s=0;
		for(i=1;i<=x[now];i++)
		{
			mtime++;
			s+=i;
			if(s>=k)
			{
				cout<<mtime<<endl;
				break;
			}
		}
		if(s>=k) continue;
		s+=x[now];
		mtime++;
		for(i=x[now]+1;1;i++)
		{
			if(s+i>k)
			{
				cout<<mtime+1<<endl;
				break;
			}
			if(s+i*2>k)
			{
				cout<<mtime+2<<endl;
				break;
			}
			s+=i*2;
			mtime+=2;
		}
	}
	return 0;
}

thank!!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章