機試編程(十)

機試編程(十)

目錄:

  1. 應用實例
    1. 還是A+B【浙江大學】
    2. Digital Roots【北京大學】
    3. 最小花費【清華大學】
    4. 日誌排序【北京大學】
    5. 位操作練習【北京大學】
    6. 字符串排序【北京大學】
    7. 加減乘除【北京大學】
    8. 二次方程計算器【上海交通大學】
    9. 棋盤遊戲【上海交通大學】
    10. 最小面積子矩陣【上海交通大學】
    11. 取中值【上海交通大學】
    12. 暢通工程【浙江大學】

一、應用實例

1、題目描述:讀入兩個小於10000的正整數A和B,計算A+B。需要注意的是:如果A和B的末尾K(不超過8)位數字相同,請直接輸出-1。【浙江大學】

  • 輸入格式:測試輸入包含若干測試用例,每個測試用例佔一行,格式爲"A B K",相鄰兩數字有一個空格間隔。當A和B同時爲0時輸入結束,相應的結果不要輸出。
  • 輸出格式:對每個測試用例輸出1行,即A+B的值或者是-1。
  • 樣例輸入:
    • 1 2 1
    • 11 21 1
    • 108 8 2
    • 36 64 3
    • 0 0 1
  • 樣例輸出:
    • 3
    • -1
    • -1
    • 100

示例代碼:

#include <iostream>

using namespace std;

int main(){
    int a, b, k, result;
    int modA, modB;
    while(cin >> a >> b >> k && a != 0 && b != 0){
        result = a + b;
        bool flag = true;
        while(a > 0 && b > 0 && k > 0){
            modA = a % 10;
            modB = b % 10;
            if(modA != modB){
                flag = false;
                break;
            }
            a /= 10;
            b /= 10;
            k--;
        }
        if(!flag){
            cout << result << endl;
        }else{
            cout << -1 << endl;
        }
    }
    return 0;
}

2、題目描述:The digital root of a positive integer is found by summing the digits of the integer. If the resulting value is a single digit then that digit is the digital root. If the resulting value contains two or more digits, those digits are summed and the process is repeated. This is continued as long as necessary to obtain a single digit.     For example, consider the positive integer 24. Adding the 2 and the 4 yields a value of 6. Since 6 is a single digit, 6 is the digital root of 24. Now consider the positive integer 39. Adding the 3 and the 9 yields 12. Since 12 is not a single digit, the process must be repeated. Adding the 1 and the 2 yeilds 3, a single digit and also the digital root of 39.【北京大學】

  • 輸入格式:The input file will contain a list of positive integers, one per line. The integer may consist of a large number of digits.
  • 輸出格式:For each integer in the input, output its digital root on a separate line of the output.
  • 樣例輸入:
    • 24
    • 39
    • 0
  • 樣例輸出:
    • 6
    • 3

示例代碼:

#include <iostream>

using namespace std;

int GetLocSum(int n){
	if(n < 10){
		return n;
	}
	int result = 0;
	while(n != 0){
		result += n % 10;
		n /= 10;
	}
	return GetLocSum(result);
}

int main(){
	int n;
	while(cin >> n && n != 0){
		cout << GetLocSum(n) << endl;
	}
	return 0;
}

3、題目描述:在某條線路上有N個火車站,有三種距離的路程,L1,L2,L3,對應的價格爲C1,C2,C3.其對應關係如下: 距離s 票價 0<S<=L1 C1 L1<S<=L2 C2 L2<S<=L3 C3 ,輸入保證0<L1<L2<L3<10^9,0<C1<C2<C3<10^9。 每兩個站之間的距離不超過L3。 當乘客要移動的兩個站的距離大於L3的時候,可以選擇從中間一個站下車,然後買票再上車,所以乘客整個過程中至少會買兩張票。 現在給你一個 L1,L2,L3,C1,C2,C3。然後是A B的值,其分別爲乘客旅程的起始站和終點站。 然後輸入N,N爲該線路上的總的火車站數目,然後輸入N-1個整數,分別代表從該線路上的第一個站,到第2個站,第3個站,……,第N個站的距離。 根據輸入,輸出乘客從A到B站的最小花費。【清華大學】

  • 輸入格式:以如下格式輸入數據:
    L1  L2  L3  C1  C2  C3
    A  B
    N
    a[2]
    a[3]
    ……
    a[N]
  • 輸出格式:可能有多組測試數據,對於每一組數據,根據輸入,輸出乘客從A到B站的最小花費。
  • 樣例輸入:
    • 1 2 3 1 2 3
    • 1 2
    • 2
    • 2
  • 樣例輸出:
    • 2

示例代碼:

#include <iostream>
#include <cstring>

using namespace std;

const int MAX_N = 500;//最大爲500個站
const int MAX_INT = 0x7fffffff;

int distList[MAX_N];//dist[i]表示從第i - 1到i站的距離
int l1, l2, l3, c1, c2, c3;
int dp[MAX_N];//dp[i]表示第i站下車的最小花費

int GetCost(int dist){
	if(dist > 0 && dist <= l1){
		return c1;
	}else if(dist > l1 && dist <= l2){
		return c2;
	}else if(dist > l2 && dist <= l3){
		return c3;
	}else{
		return 0;
	}
}

int main(){
	int begin, end, n;//begin:起始站,end:終點站,n:火車站數
	int dist;//每個站之間的距離
	while(cin >> l1 >> l2 >> l3 >> c1 >> c2 >> c3 >> begin >> end >> n){
		memset(dp, 0, sizeof(dp));
		memset(distList, 0, sizeof(distList));
		int tmp = 0;
		for(int i = 1; i < n; i++){
			cin >> dist;
			distList[i] = dist - tmp;
			tmp = dist;
		}
		int tmpLoc;
		for(int i = begin + 1; i <= end; i++){
			dp[i] = MAX_INT;
			tmpLoc = 0;
			for(int j = i - 1; j >= begin; j--){
				tmpLoc += distList[j];
				if(tmpLoc > l3){
					break;
				}
				dp[i] = min(dp[j] + GetCost(tmpLoc), dp[i]);
			}
		}
		cout << dp[end] << endl;
	}
	return 0;
}

4、題目描述:有一個網絡日誌,記錄了網絡中計算任務的執行情況,每個計算任務對應一條如下形式的日誌記錄: “hs_10000_p”是計算任務的名稱, “2007-01-17 19:22:53,315”是計算任務開始執行的時間“年-月-日 時:分:秒,毫秒”, “253.035(s)”是計算任務消耗的時間(以秒計) hs_10000_p 2007-01-17 19:22:53,315 253.035(s) 請你寫一個程序,對日誌中記錄計算任務進行排序。 時間消耗少的計算任務排在前面,時間消耗多的計算任務排在後面。 如果兩個計算任務消耗的時間相同,則將開始執行時間早的計算任務排在前面。【北京大學】

  • 輸入格式:日誌中每個記錄是一個字符串,每個字符串佔一行。最後一行爲空行,表示日誌結束。日誌中最多可能有10000條記錄。計算任務名稱的長度不超過10,開始執行時間的格式是YYYY-MM-DD HH:MM:SS,MMM,消耗時間小數點後有三位數字。計算任務名稱與任務開始時間、消耗時間之間以一個或多個空格隔開,行首和行尾可能有多餘的空格。
  • 輸出格式:排序好的日誌記錄。每個記錄的字符串各佔一行。輸入的格式與輸入保持一致,輸入包括幾個空格,你的輸出中也應該包含同樣多的空格。
  • 樣例輸入:
    • hs_10000_p   2007-01-17 19:22:53,315     253.035(s)
    • hs_10001_p   2007-01-17 19:22:53,315     253.846(s)
    • hs_10002_m   2007-01-17 19:22:53,315     129.574(s)
    • hs_10002_p   2007-01-17 19:22:53,315     262.531(s)
    • hs_10003_m   2007-01-17 19:22:53,318     126.622(s)
    • hs_10003_p   2007-01-17 19:22:53,318     136.962(s)
    • hs_10005_m   2007-01-17 19:22:53,318     130.487(s)
    • hs_10005_p   2007-01-17 19:22:53,318     253.035(s)
    • hs_10006_m   2007-01-17 19:22:53,318     248.548(s)
    • hs_10006_p   2007-01-17 19:25:23,367    3146.827(s)
  • 樣例輸出:
    • hs_10003_m   2007-01-17 19:22:53,318     126.622(s)
    • hs_10002_m   2007-01-17 19:22:53,315     129.574(s)
    • hs_10005_m   2007-01-17 19:22:53,318     130.487(s)
    • hs_10003_p   2007-01-17 19:22:53,318     136.962(s)
    • hs_10006_m   2007-01-17 19:22:53,318     248.548(s)
    • hs_10000_p   2007-01-17 19:22:53,315     253.035(s)
    • hs_10005_p   2007-01-17 19:22:53,318     253.035(s)
    • hs_10001_p   2007-01-17 19:22:53,315     253.846(s)
    • hs_10002_p   2007-01-17 19:22:53,315     262.531(s)
    • hs_10006_p   2007-01-17 19:25:23,367    3146.827(s)

示例代碼1:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

struct Node{
	string str;
	string name;
	string day;
	string time;
	double mTime;
	Node(string s):str(s){};
};

bool CompareDesc(const Node &n1, const Node &n2){
	if(n1.mTime == n2.mTime){
		if(n1.day == n2.day){
			return n1.time < n2.time;
		}
		return n1.day < n2.day;
	}
	return n1.mTime < n2.mTime;
}

string GetString(string s, int &index, int len){
	string result = "";
	while(index < len && s[index] != ' '){
		result += s[index++];
	}
	return result;
}

double StringTodouble(string s, int len){
	int frontResult = 0, backResult = 0;
	int pointLoc = s.find('.');
	int index = 0;
	if(pointLoc != s.npos){ //有小數點
		while(index < pointLoc){
			frontResult = frontResult * 10 + s[index++] - '0';
		}
		index++;
	}
	while(index < len){
		backResult = backResult * 10 + s[index++] - '0';
	}
	return frontResult + backResult / 1000.0;
}

int main(){
	vector<Node> nodeList;
	string s;
	while(getline(cin , s)){
		int index = 0, len = s.size(), paramNum = 1;
		Node node = Node(s);
		while(index < len){
			if(s[index] != ' '){
				string paramStr = GetString(s, index, len);
				if(paramNum == 1){
					node.name = paramStr;
				}else if(paramNum == 2){
					node.day = paramStr;
				}else if(paramNum == 3){
					node.time = paramStr;
				}else if(paramNum == 4){
					int len2 = paramStr.size() - 3;
					node.mTime = StringTodouble(paramStr.substr(0, len2), len2);
				}
				paramNum++;
			}else{
				index++;
			}
		}
		nodeList.push_back(node);
	}
	sort(nodeList.begin(), nodeList.end(), CompareDesc);
	for(int i = 0; i < nodeList.size(); i++){
		cout << nodeList[i].str << endl;
	}
	return 0;
}

示例代碼2(使用sscanf):

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;

struct Node{
	char str[100];
	char name[11];
	char day[30];
	char time[20];
	double mTime;
}nodeList[10000];

bool CompareDesc(const Node &n1, const Node &n2){
	if(n1.mTime == n2.mTime){
		if(strcmp(n1.day, n2.day) == 0){
			return strcmp(n1.time, n2.time) < 0;
		}
		return strcmp(n1.day, n2.day) < 0;
	}
	return n1.mTime < n2.mTime;
}

double CharArrayTodouble(char s[]){
	int len = strlen(s) - 3;
	int frontResult = 0, backResult = 0;
	int pointLoc = 0;
	for(int i = 0; i < len; i++){
		if(s[i] == '.'){
			pointLoc = i;
			break;
		}
	}
	int index = 0;
	if(pointLoc != 0){ //有小數點
		while(index < pointLoc){
			frontResult = frontResult * 10 + s[index++] - '0';
		}
		index++;
	}
	while(index < len){
		backResult = backResult * 10 + s[index++] - '0';
	}
	return frontResult + backResult / 1000.0;
}

int main(){
	int k = 0;
	char mTime[20];
	while(gets(nodeList[k].str)){
		sscanf(nodeList[k].str, "%s%s%s%s", nodeList[k].name, nodeList[k].day, nodeList[k].time, mTime);
		nodeList[k].mTime = CharArrayTodouble(mTime);
		k++;
	}
	sort(nodeList, nodeList + k, CompareDesc);
	for(int i = 0; i < k; i++){
		cout << nodeList[i].str << endl;
	}
	return 0;
}

5、題目描述:給出兩個不大於65535的非負整數,判斷其中一個的16位二進制表示形式,是否能由另一個的16位二進制表示形式經過循環左移若干位而得到。 循環左移和普通左移的區別在於:最左邊的那一位經過循環左移一位後就會被移到最右邊去。比如: 1011 0000 0000 0001 經過循環左移一位後,變成 0110 0000 0000 0011, 若是循環左移2位,則變成 1100 0000 0000 0110【北京大學】

  • 輸入格式:每行有兩個不大於65535的非負整數
  • 輸出格式:對於每一行的兩個整數,輸出一行,內容爲YES或NO
  • 樣例輸入:
    • 2 4
    • 9 18
    • 45057 49158
    • 7 12
  • 樣例輸出:
    • YES
    • YES
    • YES
    • NO

示例代碼1(將兩個字符串都先轉換爲二進制串,再進行比較):

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

const int STR_LENGTH = 16;

string DecimalToBinary(int n, int &oneNumer){
	string result;
	char c;
	while(n != 0){
		if(n % 2 == 1){
			oneNumer++;
		}
		c = n % 2 + '0';
		result = c + result;
		n /= 2;
	}
	return result;
}

int main(){
	int a, b, aOneCount, bOneCount;
	string aStr, bStr;
	while(cin >> a >> b){
		aOneCount = bOneCount = 0;
		aStr = DecimalToBinary(a, aOneCount);
		
		bStr = DecimalToBinary(b, bOneCount);
		
		while(aStr.size() < STR_LENGTH){
			aStr = '0' + aStr;
		}
		while(bStr.size() < STR_LENGTH){
			bStr = '0' + bStr;
		}
		if(bStr.size() < aStr.size()){
			cout << "NO" << endl;
		}else{
			bool flag = false;
			for(int i = 0; i < STR_LENGTH; i++){
				aStr = aStr.substr(1) + aStr[0];
				if(aStr == bStr){
					flag = true;
					break;
				}
			}
			if(flag){
				cout << "YES" << endl;
			}else{
				cout << "NO" << endl;
			}
		}
	}
	return 0;
}

示例代碼2(利用位操作):

#include <iostream>

using namespace std;

int main(){
	unsigned short a, b;
	while(cin >> a >> b){
		bool flag = false;
		for(int i = 0; i < 16; i++){
			if(a == b){
				flag = true;
				break;;
			}
			a = a >> 1 | a << 15;
		}
		if(flag){
			cout << "YES" << endl;
		}else{
			cout << "NO" << endl;
		}
		
	}
	return 0;
}

附註:

(1)循環左移:如a = 01111011,循環左移兩位,得11101101,分步實現爲:b = a >> (8,2),右移六位,用來得到正常左移丟失的位,其正確位置,a = a << 2,左移兩位,得到11101100,a = a | b

6、題目描述:先輸入你要輸入的字符串的個數。然後換行輸入該組字符串。每個字符串以回車結束,每個字符串少於一百個字符。 如果在輸入過程中輸入的一個字符串爲“stop”,也結束輸入。 然後將這輸入的該組字符串按每個字符串的長度,由小到大排序,按排序結果輸出字符串。【北京大學】

  • 輸入格式:字符串的個數,以及該組字符串。每個字符串以‘\n’結束。如果輸入字符串爲“stop”,也結束輸入.
  • 輸出格式:可能有多組測試數據,對於每組數據,將輸入的所有字符串按長度由小到大排序輸出(如果有“stop”,不輸出“stop”)。根據輸入的字符串個數來動態分配存儲空間(採用new()函數)。每個字符串會少於100個字符。測試數據有多組,注意使用while()循環輸入。
  • 樣例輸入:
    • 5
    • sky is grey
    • cold
    • very cold
    • stop
    • 3
    • it is good enough to be proud of
    • good
    • it is quite good
  • 樣例輸出:
    • cold
    • very cold
    • sky is grey
    • good
    • it is quite good
    • it is good enough to be proud of

示例代碼:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int MAX_N = 101;
const int MAX_CASE = 500;

struct Node{
	char a[MAX_N];
};

bool CompareAsc(const Node p1, const Node p2){
	return strlen(p1.a) < strlen(p2.a);
}

int main(){
	int n;
	while(scanf("%d", &n) != EOF){
		getchar();
		Node *p = new Node[MAX_CASE];
		int index;
		for(index = 0; index < n; index++){
			gets(p[index].a);
			if(strcmp(p[index].a, "stop") == 0){
				break;
			}
		}
		sort(p, (p + index), CompareAsc);
		for(int i = 0; i < index; i++){
			printf("%s\n", p[i].a);
		}
	}
	return 0;
}

7、題目描述:根據輸入的運算符對輸入的整數進行簡單的整數運算。 運算符只會是加+、減-、乘*、除/、求餘%、階乘!六個運算符之一。 輸出運算的結果,如果出現除數爲零,則輸出“error”,如果求餘運算的第二個運算數爲0,也輸出“error”。【北京大學】

  • 輸入格式:輸入爲一行。先輸入第一個整數,空格輸入運算符,然後再空格輸入第二個整數,回車結束本次輸入。如果運算符爲階乘!符號,則不輸入第二個整數,直接回車結束本次輸入。
  • 輸出格式:可能有多組測試數據,對於每組數據,輸出一行。輸出對輸入的兩個(或一個)數,根據輸入的運算符計算的結果,或者“error”。
  • 樣例輸入:
    • 12 + 34
    • 54 - 25
    • 3 * 6
    • 45 / 0
    • 5 !
    • 34 % 0
  • 樣例輸出:
    • 46
    • 29
    • 18
    • error
    • 120
    • error

示例代碼:

#include <iostream>

using namespace std;

int main(){
	char oper;
	int a, b;
	while(cin >> a >> oper){
		if(oper == '!'){
			long long result = 1;
			for(int i = 1; i <= a; i++){
				result *= i;
			}
			cout << result << endl;
		}else{
			cin >> b;
			if(oper == '+'){
				cout << a + b << endl;
			}else if(oper == '-'){
				cout << a - b << endl;
			}else if(oper == '*'){
				cout << a * b << endl;
			}else if(b == 0){
				cout << "error" << endl;
			}else{
				if(oper == '%'){
					cout << a % b << endl;
				}else if(oper == '/'){
					cout << a / b << endl;
				}
			}
		}
	}
	return 0;
}

8、題目描述:設計一個二次方程計算器【上海交通大學】

  • 輸入格式:每個案例是關於x的一個二次方程表達式,爲了簡單,每個係數都是整數形式。
  • 輸出格式:每個案例輸出兩個實數(由小到大輸出,中間由空格隔開),保留兩位小數;如果無解,則輸出“No Solution”。
  • 樣例輸入:
    • x^2+x=3x+4
  • 樣例輸出:
    • -1.24 3.24

示例代碼:

#include <iostream>
#include <string>
#include <iomanip>
#include <algorithm>

using namespace std;

struct Node{ //ax^2 + bx + c = 0;
	int a;
	int b;
	int c;
	Node(int a, int b, int c):a(a), b(b), c(c){};
};

int GetNumber(string s, int &index){
	int result = 0;
	while(s[index] >= '0' && s[index] <= '9'){
		result = result * 10 + s[index] - '0';
		index++;
	}
	return result;
}

int main(){
	string s;
	while(getline(cin ,s)){
		Node node(0, 0, 0);
		int i = 0, len = s.size(), param;
		//operFlag判斷是否爲正負號,正號爲true;equalFlag判斷爲等式的左右部分,左true
		bool operFlag = true, equalFlag = true;
		while(i < len){
			param = 0;
			if(s[i] == '='){
				equalFlag = false;
				operFlag = false; //右邊部分默認操作符爲減
			}
			if(s[i] == '-' || s[i] == '+'){
				if((s[i] == '-' && equalFlag) || (s[i] == '+' && !equalFlag)){
					operFlag = false;
				}else{
					operFlag = true;
				}
			}else if(s[i] >= '0' && s[i] <= '9'){
				param = GetNumber(s, i);
				if(!operFlag){
					param *= -1;
				}
			}
			if(i < len && s[i] == 'x'){
				if(param == 0){
					param = 1;
				}
				if(i + 1 < len && s[i + 1] == '^'){ //二次項係數
					node.a += param;
					i += 2;
				}else{
					node.b += param;
				}
			}else{
				node.c += param;
			}
			i++;
		}
		int delta = node.b * node.b - 4 * node.a * node.c;
		if(delta < 0){
			cout << "No Solution" << endl;
		}else if(delta == 0){
			double result = -node.b / 2 / node.a;
			cout << fixed << setprecision(2) << result << result << endl;
		}else{
			double sqrtValue = sqrt(delta);
			double value1 = (-node.b - sqrtValue) / 2 / node.a;
			double value2 = (-node.b + sqrtValue) / 2 / node.a;
			if(value1 < value2){
				cout << fixed << setprecision(2) <<  value1 << " " << value2 << endl;
			}else{
				cout << fixed << setprecision(2) <<  value2 << " " << value1 << endl;
			}
		}
	}
	return 0;
}

9、題目描述:有一個6*6的棋盤,每個棋盤上都有一個數值,現在有一個起始位置和終止位置,請找出一個從起始位置到終止位置代價最小的路徑:     1、只能沿上下左右四個方向移動     2、總代價是每走一步的代價之和     3、每步(從a,b到c,d)的代價是c,d上的值與其在a,b上的狀態的乘積     4、初始狀態爲1     每走一步,狀態按如下公式變化:(走這步的代價%4)+1。【上海交通大學】

  • 輸入格式:每組數據一開始爲6*6的矩陣,矩陣的值爲大於等於1小於等於10的值,然後四個整數表示起始座標和終止座標。
  • 輸出格式:輸出最小代價。
  • 樣例輸入:
    • 1 1 1 1 1 1
    • 1 1 1 1 1 1
    • 1 1 1 1 1 1
    • 1 1 1 1 1 1
    • 1 1 1 1 1 1
    • 1 1 1 1 1 1
    • 0 0 5 5
  • 樣例輸出:
    • 23

示例代碼:

#include <iostream>
#include <cstring>

using namespace std;

const int MAX_N = 6;
const int MAX_INT = 0x7fffffff;

int matrix[MAX_N][MAX_N];//棋盤
int visit[MAX_N][MAX_N]; //結點是否已訪問
int fromX, fromY, toX, toY;
int ans;
int direct[4][2] = {
	{1, 0}, {0, 1}, {-1, 0}, {0, -1}
};

//price爲到x,y結點的代價,status爲上一步的狀態,x、y爲下一步要去的結點
void DFS(int x, int y, int status, int price){
	if(x == toX && y == toY){
		ans = min(ans, price);
		return;
	}
	if(price >= ans){
		return;
	}
	visit[x][y] = 1;
	int newX, newY, newPrice, newStatus;//去下一步的代價,下一步的狀態,下一步的x、y
	for(int i = 0; i < 4; i++){
		newX = x + direct[i][0];
		newY = y + direct[i][1];
		if(newX < MAX_N && newY < MAX_N && newX >= 0 && newY >= 0 && visit[newX][newY] == 0){
			newPrice = status * matrix[newX][newY];
			newStatus = (newPrice % 4) + 1;
			DFS(newX, newY, newStatus, price + newPrice);
		}
	}
	visit[x][y] = 0;
}

int main(){
	while(cin >> matrix[0][0]){
		for(int i = 1; i < MAX_N; i++){
			cin >> matrix[0][i];
		}
		for(int i = 1; i < MAX_N; i++){
			for(int j = 0; j < MAX_N; j++){
				cin >> matrix[i][j];
			}
		}
		cin >> fromX >> fromY >> toX >> toY;
		memset(visit, 0, sizeof(visit));
		//深度優先
		ans = MAX_INT;
		DFS(fromX, fromY, 1, 0);
		cout << ans << endl;
	}
	return 0;
}

10、題目描述:一個N*M的矩陣,找出這個矩陣中所有元素的和不小於K的面積最小的子矩陣(矩陣中元素個數爲矩陣面積)【上海交通大學】

  • 輸入格式:每個案例第一行三個正整數N,M<=100,表示矩陣大小,和一個整數K。接下來N行,每行M個數,表示矩陣每個元素的值
  • 輸出格式:輸出最小面積的值。如果出現任意矩陣的和都小於K,直接輸出-1。
  • 樣例輸入:
    • 4 4 10
    • 1 2 3 4
    • 5 6 7 8
    • 9 10 11 12
    • 13 14 15 16
  • 樣例輸出:
    • 1

示例代碼:

#include <iostream>
#include <cstring>

using namespace std;

const int MAX_N = 101;
const int MAX_INT = 0x7fffffff;

int matrix[MAX_N][MAX_N];
int Short[MAX_N][MAX_N];//Short[i][j]表示從i到j的距離
int sum, result, resultRow;//sum用於求和整個數組所有元素,result爲輸出結果
int merge[MAX_N];
int n, m, k;

void GetShort(){
	memset(Short, 0, sizeof(Short));
	for(int i = 0; i < m; i++){
		for(int j = i; j < m; j++){
			if(j == i){
				Short[i][j] = merge[i];
			}else{
				Short[i][j] = Short[i][j - 1] + merge[j];
			}
			if(Short[i][j] >= k){
				if(resultRow * (j - i + 1) < result){
					result = resultRow * (j - i + 1);
				}
				break;
			}
		}
	}
}

int main(){
	while(cin >> n >> m >> k){
		sum = 0;
		result = MAX_INT;
		for(int i = 0; i < n; i++){
			for(int j = 0; j < m; j++){
				cin >> matrix[i][j];
				sum += matrix[i][j];
			}
		}
		if(sum < k){
			cout << "-1" << endl;
		}else{
			for(int i = 0; i < n; i++){
				for(int j = i; j < n; j++){//將第i行到第j行合併
					if(j - i + 1 >= result){
						break;
					}else{
						memset(merge, 0, sizeof(merge));
						for(int p = 0; p < m; p++){
							for(int k = i; k <= j; k++){
								merge[p] += matrix[k][p];
							}
						}
						resultRow = j - i + 1;
						GetShort();
					}
				}
			}
			cout << result << endl;
		}
	}
	return 0;
}

11、題目描述:存在兩組數組,和4個數字a,b,c,d,要求做如下操作,將第一個數組第a個數到第b個數,第二個數組的第c個數到第d個數放到一個數組中,求出合併後數組的中間值,如果有兩個中間值,取下標較小的那個。【上海交通大學】

  • 輸入格式:第一行兩個整數,表示兩個數組的長度,接下來兩行表示兩個數組的值,最後一行有四個整數a,b,c,d。數組長度不會超過1000000。
  • 輸出格式:每行一個整數,對應合併數組的下標在中間的那個值。
  • 樣例輸入:
    • 5 4
    • 1 2 3 4 5
    • 6 7 8 9
    • 1 2 1 3
  • 樣例輸出:
    • 6

示例代碼:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

vector<int> a, b;

int main(){
	int len1, len2;
	int aFrom, aTo, bFrom, bTo;
	int inputNum;
	while(cin >> len1 >> len2){
		a.clear();
		b.clear();
		for(int i = 0; i < len1; i++){
			cin >> inputNum;
			a.push_back(inputNum);
		}
		for(int i = 0; i < len2; i++){
			cin >> inputNum;
			b.push_back(inputNum);
		}
		cin >> aFrom >> aTo >> bFrom >> bTo;
		int part1 = aTo - aFrom + 1;
		int part2 = bTo - bFrom + 1;
		int middle = (part1 + part2 - 1) / 2;
		if(part1 > middle){
			cout << a[aFrom + middle + 1] << endl;
		}else{
			cout << b[bFrom - 1 + middle - part1] << endl;
		}
	}
	return 0;
}

12、題目描述:省政府“暢通工程”的目標是使全省任何兩個村莊間都可以實現公路交通(但不一定有直接的公路相連,只要能間接通過公路可達即可)。經過調查評估,得到的統計表中列出了有可能建設公路的若干條道路的成本。現請你編寫程序,計算出全省暢通需要的最低成本。【浙江大學】

  • 輸入格式:測試輸入包含若干測試用例。每個測試用例的第1行給出評估的道路條數 N、村莊數目M (N, M < =100 );隨後的 N 行對應村莊間道路的成本,每行給出一對正整數,分別是兩個村莊的編號,以及此兩村莊間道路的成本(也是正整數)。爲簡單起見,村莊從1到M編號。當N爲0時,全部輸入結束,相應的結果不要輸出。
  • 輸出格式:對每個測試用例,在1行裏輸出全省暢通需要的最低成本。若統計數據不足以保證暢通,則輸出“?”。
  • 樣例輸入:
    • 3 3
    • 1 2 1
    • 1 3 2
    • 2 3 4
    • 1 3
    • 2 3 2
    • 0 100
  • 樣例輸出:
    • 3
    • ?

示例代碼:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

//並查集 + 貪心
const int MAX_N = 101;
int father[MAX_N];
int height[MAX_N];

struct Node{
	int from;
	int to;
	int price;
	Node(int f, int t, int p):from(f), to(t), price(p){};
};

vector<Node> myList;

void Init(int m){
	myList.clear();
	for(int i = 1; i <= m; i++){
		father[i] = i;
		height[i] = 0;
	}
}

int GetFather(int n){
	while(n != father[n]){
		n = father[n];
	}
	return father[n];
}

bool Union(int x, int y){
	x = GetFather(x);
	y = GetFather(y);
	if(x != y){
		if(height[x] < height[y]){
			father[x] = y;
		}else if(height[y] < height[x]){
			father[y] = x;
		}else{
			father[x] = y;
			height[y]++;
		}
		return false;
	}
	return true;
}

bool Compare(const Node &n1, const Node &n2){
	return n1.price < n2.price;
}

int main(){
	int n, m;//n條路,m個村
	int from, to, price;
	while(cin >> n >> m && n != 0){
		Init(m);
		for(int i = 0; i < n; i++){
			cin >> from >> to >> price;
			myList.push_back(Node(from, to, price));
		}
		sort(myList.begin(), myList.end(), Compare);
		int result = 0, unionCount = 0;
		for(int i = 0; i < myList.size(); i++){
			if(!Union(myList[i].from, myList[i].to)){
				result += myList[i].price;
			}
		}
		for(int i = 1 ; i <= m; i++){
			if(father[i] == i){
				unionCount++;
			}
		}
		if(unionCount == 1){
			cout << result << endl;
		}else{
			cout << "?" << endl;
		}
		
	}
	return 0;
}

 

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