1. 程式人生 > >PAT 乙級 採花生 (模擬)

PAT 乙級 採花生 (模擬)

---------------------------------處女blog------------------------逃…

題目描述

    魯賓遜先生有一隻寵物猴,名叫多多。這天,他們兩個正沿著鄉間小路散步,突然發現路邊的告示牌上貼著一張小小的紙條:“歡迎免費品嚐我種的花生!——熊字”。
    魯賓遜先生和多多都很開心,因為花生正是他們的最愛。在告示牌背後,路邊真的有一塊花生田,花生植株整齊地排列成矩形網格。有經驗的多多一眼就能看出,每棵花生植株下的花生有多少。為了訓練多多的算術,魯賓遜先生說:“你先找出花生最多的植株,去採摘它的花生;然後再找出剩下的植株裡花生最多的,去採摘它的花生;依此類推,不過你一定要在我限定的時間內回到路邊。”
    我們假定多多在每個單位時間內,可以做下列四件事情中的一件:

1. 從路邊跳到最靠近路邊(即第一行)的某棵花生植株;
2. 從一棵植株跳到前後左右與之相鄰的另一棵植株;
3. 採摘一棵植株下的花生;
4. 從最靠近路邊(即第一行)的某棵花生植株跳回路邊。

現在給定一塊花生田的大小和花生的分佈,請問在限定時間內,多多最多可以採到多少個花生?

注意可能只有部分植株下面長有花生,假設這些植株下的花生個數各不相同。例如花生田裡只有位於(2, 5), (3,7), (4, 2), (5, 4)的植株下長有花生,個數分別為 13, 7, 15, 9。多多在 21 個單位時間內,只能經過(4, 2)、(2, 5)、(5, 4),最多可以採到37 個花生。

輸入描述:

輸入包含多組資料,每組資料第一行包括三個整數 M(1≤M≤20)、N(1≤N≤20)和 K(0≤K≤1000),用空格隔開;表示花生田的大小為 M * N,多多采花生的限定時間為 K個單位時間。
緊接著 M 行,每行包括 N 個自然數 P(0≤P≤500),用空格隔開;表示花生田裡植株下花生的數目,並且除了0(沒有花生),其他所有植株下花生的數目都不相同。

輸出描述:

對應每一組資料,輸出一個整數,即在限定時間內,多多最多可以採到花生的個數。

輸入例子:

6 7 21
0 0 0 0 0 0 0
0 0 0 0 13 0 0
0 0 0 0 0 0 7
0 15 0 0 0 0 0
0 0 0 9 0 0 0
0 0 0 0 0 0 0

輸出例子:

37

--------------------------------------------------------solution-----------------------------------------------

#include <stdio.h>
int next_step1(int first, int second) { //計算採花生的兩個點,行之間的距離 
	if (first / 100>second / 100)
		return (first / 100 - second / 100);
	else return (second / 100 - first / 100);
}
int next_step2(int first, int second) { //計算採花生的兩個點,列之間的距離 
	if (first % 100>second % 100)
		return (first % 100 - second % 100);
	else return (second % 100 - first % 100);
}

int main()
{
	int m, n, k = 0, i, j;
	while (scanf("%d%d%d", &m, &n, &k) != EOF) {  //輸入陣列 
		int a[20][20], b[400], c[400];
		for (i = 0; i<m; i++)
			for (j = 0; j<n; j++)
				scanf("%d", &a[i][j]);

		int q = 0, maxq = 0, temptb = 0, temptc = 0;
		for (i = 0; i<m; i++)   //二維陣列轉換為一維陣列 b 
			for (j = 0; j<n; j++) {
				b[q] = a[i][j];
				c[q] = i * 100 + j;  //二維陣列換算,把下標進行換算 ”行*100+列“並存儲到一維陣列c中  
				q++;
			}
		for (maxq = 0; maxq<m*n; maxq++) //一維陣列b和c排序,從大到小 
		{
			for (q = 0; q<m*n; q++)
				if (b[q]<b[maxq]) {
					temptb = b[maxq];
					b[maxq] = b[q];
					b[q] = temptb;

					temptc = c[maxq];
					c[maxq] = c[q];
					c[q] = temptc;
				}
		}
		//計算在k值下,最短路徑
		int step = 0, carrot = 0, fstep = 0;
		int next_step1(int first, int second);
		int next_step2(int first, int second);

		if ((c[0] / 100 * 2 + 3)>k)
			printf("%d\n", carrot);
		else {
			step = c[0] / 100 + 2;
			carrot = carrot + b[0];

			for (q = 1; q<m*n; q++) {  //這裡要注意迴圈結束的條件
				step = step + next_step1(c[q], c[q - 1]) + next_step2(c[q], c[q - 1]);
				if ((step + 2 + c[q] / 100)>k) break;
				step = step + 1;
				carrot = carrot + b[q];
			}
			printf("%d\n", carrot);
		}
	}
	return 0;
}

---------------------------------------------思路總結--------------

     因為沒有學過任何的演算法之類的,是最近才開始撿起扔了兩年的C語言的,因此用的是最笨的方法,暴力解。

    首先是將花生田放入二維陣列中,然後將二維陣列轉換為一維陣列,對一維陣列進行排序,當然,在二維與一維的轉換過程中需要建立另一個數組,對花生的座標進行記錄,為保證記錄的座標資料在後面可以用來計算採花生的步數,由於題設要求行列不超過20,所以我採用了對行進行加權,用行x100,列保持不變。對加權後的座標陣列元素,可以得到類似301、102等資料,如301表示,該花生在第三行,第一列,計算301到102需要移動的步數為301的百位數減去102的百位數,即3-1=2,剩下的個、十位數相減,即為列之間的步數02-01=1,所以從301走到102共需要1+2=3步,在做減法的時候,需要先將座標資訊提取,然後取相減的絕對值,即大的減小的。此外,還需注意一些細節問題,即迴圈的結束條件等。