机试编程(十)

机试编程(十)

目录:

  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;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值