1-2 暴力破解-模拟

模拟:根据题目要求编写代码
可分为:图形排版(根据某种规则输出特定图形)、日期问题、其他模拟

一.图形排版
1.输出梯形(清华大学)

1-2 暴力破解-模拟_第1张图片

法一:等差数列
分析:每行的星号个数为等差数列2n+2(n=1,2,3,…)

#include
using namespace std;
int main() {
	int n = 0;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int j = 0;
		for (; j < 2 * n + 2 - (2 * i + 2); j++) {
			cout << " ";
		}
		for (; j < 2 * n + 2; j++) {
			cout << "*";
		}
		cout << endl;
	}
}

法二:梯形求解
分析:设第0行有h个星号,第1行有h+2个,第2行有h+2* 2个,第i行有h+2* i个
若该梯形的高为h,则最后一行是第h-1行,星号数为h+2* (h-1)
则第一行的空格数=h+2* (h-1)-h
第i行的空格数=h+2* (h-1)-(h+2* i)=2(h-1-i)个

即第i行的空格数为2(h-1-i)个,星号数为h+2* i个

#include
using namespace std;
int main() {
	int h=0;
	while (scanf("%d",&h) != EOF) {
		for (int i = 0; i < h; i++) {
			for (int j = 0; j < 2 * (h - 1 - i); j++) {
				cout << " ";
			}
			for (int j = 0; j < h+2*i; j++) {
				cout << "*";
			}
			cout << endl;
		}
	}
}

2.叠筐(杭州电子科技大学-2074)

1-2 暴力破解-模拟_第2张图片
1-2 暴力破解-模拟_第3张图片
1-2 暴力破解-模拟_第4张图片

评测系统

法一:

#include
using namespace std;
int main() {
	int n=0;
	char b, a;
	while (cin >> n) {
		cin >> b >> a;
		string out[100];
		int count = 0;
		//特殊处理
		if (n == 1) {
			cout << b <<endl << endl;
			continue;
		}
		//决定开头字符
		if ((n - 1) / 2 % 2 == 0) {
			int temp = a;
			a = b;
			b = temp;
		}
		//第一行
		out[count] += " ";
		for (int i = 0; i < n - 2; i++) {
			out[count] += a;
		}
		out[count] += " ";
		count++;
		//第二行往后
		int num = 0;
		char arr[100] = { 0 };
		for (int i = 0; i < n / 2; i++) {
			if (i) {
				int temp = a;
				a = b;
				b = temp;
			}
			arr[num] = a;
			arr[n - num] = a;
			for (int j = 0; j <= num; j++) {
				out[count] += arr[j];
			}
			for (int j = num + 1; j < n - num - 1; j++) {
				out[count] += b;
			}
			for (int j = n - num; j <= n; j++) {
				out[count] += arr[j];
			}
			num++;
			count++;
		}
		//输出
		for (int i = 0; i < count; i++) {
			cout << out[i] << endl;
		}
		for (int i = count - 2; i >= 0; i--) {
			cout << out[i] << endl;
		}
		cout << endl;
	}
}

法二:
先补全四个角,可以看出,这是一个同心正方形,边长为n

1-2 暴力破解-模拟_第5张图片

以最外层左上角为坐标原点(0,0),向下向右展开坐标轴,右下角坐标为(n-1,n-1),最外层正方形边长为n
对于任意内层正方形,设左上角的坐标为(i,i),右下角的坐标为(j,j),则该正方形边长为n-2i
(i,i)和(j,j)两坐标相加即可得到右下角的坐标(n-1,n-1),因此有等式i+j=n-1成立

i的取值从0到n/2,当i=n/2时为中心花色

1-2 暴力破解-模拟_第6张图片
设输入的第一个字符是B,第二个字符是A

中心花色是第一个输入字符
在这里插入图片描述
向外圈填充,距离中心距离为1填充字符为第二个输入字符
在这里插入图片描述
向外圈填充,距离为2填充第一个输入字符
1-2 暴力破解-模拟_第7张图片
以此类推,左上角坐标(i,i)距离中心的距离=n/2-i
距离为奇数填充第二个输入字符
距离为偶数填充第一个输入字符

char c;//当前圈层填充的字符
if ((n / 2 - i) % 2 == 0) {//偶数
	c = 第一个输入字符;
}
else {
	c = 第二个输入字符;
}

1-2 暴力破解-模拟_第8张图片

完整代码

#include
using namespace std;
char matrix[80][80];//输出数组
int main() {
	int n;
	char a, b;
	bool firstCase = true;
	while (scanf("%d %c %c", &n, &a, &b) != EOF) {
		if (firstCase == true) {
			firstCase = false;//第一组前面无需换行
		}
		else { //在运行前先输出换行,确保两组用例之间有换行
			printf("\n");
		}
		for (int i = 0; i <= n / 2; i++) {//(i,i)为某正方形左上角坐标
			int j = n - 1 - i;//(j,j)为某正方形右下角坐标
			int length = n - 2 * i;//正方形边长
			char c;//当前圈层填充的字符
			if ((n / 2 - i) % 2 == 0) {//偶数
				c = a;
			}
			else {
				c = b;
			}
			for (int k = 0; k < length; k++) {//为当前圈层赋值
				matrix[i][i + k] = c;//上边赋值
				matrix[i+k][i] = c;//左边赋值
				matrix[j][j-k] = c;//下边赋值
				matrix[j-k][j] = c;//右边赋值
			}
		}
		if (n != 1) {//剔除四个角,确保外框尺寸n=1时也有输出,此时输出的是中心花色
			matrix[0][0] = ' ';
			matrix[0][n - 1] = ' ';
			matrix[n - 1][0] = ' ';
			matrix[n - 1][n - 1] = ' ';
		}
		for (int i = 0; i < n; i++) {//输出
			for (int j = 0; j < n; j++) {
				printf("%c", matrix[i][j]);
			}
			printf("\n");
		}
	}
	return 0;
}

3.Hello World for U(浙江大学)
1-2 暴力破解-模拟_第9张图片
1-2 暴力破解-模拟_第10张图片
评测系统

#include
#include
using namespace std;
int main() {
	string n;
	while (cin >> n) {
		int len = n.length();
		int n1, n2;
		int flag = 0;
		for (n1 = len - 1; n1 >= 2; n1--) {
			for (n2 = len - 1; n2 >= 3; n2--) {
				if (2 * n1 + n2 - 2 == len && n1 <= n2) {
					flag = 1;
					break;
				}
			}
			if (flag == 1) {
				break;
			}
		}
		flag = 0;
		char a[1000][1000];
		int num = 0;
		int i, j;
		for (i = 0; i < n1; i++) {
			a[i][0] = n[num];
			num++;
		}
		i -= 1;
		for (j = 1; j < n2; j++) {
			a[i][j] = n[num];
			num++;
		}
		j -= 1;
		for (int k = i - 1; k >= 0; k--) {
			a[k][j] = n[num];
			num++;
		}
		for (i = 0; i < n1 - 1; i++) {
			int ko = n2 - 2;
			cout << a[i][0];
			while (ko--) {
				cout << " ";
			}
			cout << a[i][n2 - 1] << endl;
		}
		for (j = 0; j < n2; j++) {
			cout << a[i][j];
		}
		cout << endl;
	}
}

二.日期问题

1-2 暴力破解-模拟_第11张图片

【求天数】
1.今年的第几天?(清华大学)
1-2 暴力破解-模拟_第12张图片

评测系统

#include
#include
using namespace std;
int count(int m,int y) {
	int sum=0;
	for (int i = 1; i <= m; i++) {
		if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12) {
			sum += 31;
		}
		else if (i == 2) {
			if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) {
				sum += 29;
			}
			else
				sum += 28;
		}
		else
			sum += 30;
	}
	return sum;
}
int main() {
	int year, month, day;
	while (cin >> year >> month >> day) {
		cout << count(month - 1, year) + day << endl;
	}
}

另一种方式

#include
#include
using namespace std;
int daytab[2][13] = {
	{0,31,28,31,30,31,30,31,31,30,31,30,31},//不是闰年
	{0,31,29,31,30,31,30,31,31,30,31,30,31},//是闰年
};
bool IsLeapYear(int year) {//是否闰年
	return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main() {
	int year, month, day;
	int number=0;
	while (scanf("%d%d%d", &year, &month,&day) != EOF) {
		int number = 0;
		int row = IsLeapYear(year);
		for (int j = 0; j < month; ++j) {
			number += daytab[row][j];
		}
		number += day;
		printf("%d\n", number);
	}
	return 0;
}

【求日期B】
2.打印日期(华中科技大学)

1-2 暴力破解-模拟_第13张图片
评测系统

#include
#include
using namespace std;
int a[2];
void count(int y,int x) {
	int sum=0;
	int premonthday2 = 0;//上个月
	int premonthday3 = 0;//上上个月
	for (int i = 1; i <= 12; i++) {
		if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12) {
			sum += 31;
			premonthday2 = 31;
		}
		else if (i == 2) {
			if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) {
				sum += 29;
				premonthday2 = 29;
			}
			else {
				sum += 28;
				premonthday2 = 28;
			}
		}
		else {
			sum += 30;
			premonthday2 = 30;
		}
		if (x < sum) {
			if (i != 1) {
				a[0] = i;
			}
			else {
				a[0] = 1;
			}
			a[1] = x+premonthday2-sum;
			if (a[1] == 0) {
				a[0] -= 1;
				a[1] = premonthday3;
			}
			return;
		}
		premonthday3 = premonthday2;
	}
}
int main() {
	int year, month, day;
	int daycount;
	while (cin >> year>> daycount) {
		count(year,daycount);
		printf("%04d-%02d-%02d\n", year, a[0], a[1]);
	}
}

另一种方式

#include
#include
using namespace std;
int daytab[2][13] = {
	{0,31,28,31,30,31,30,31,31,30,31,30,31},//不是闰年
	{0,31,29,31,30,31,30,31,31,30,31,30,31},//是闰年
};
bool IsLeapYear(int year) {//是否闰年
	return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main() {
	int year, month, day;
	int number;
	while (scanf("%d%d", &year, &number) != EOF) {
		month = 0;
		int row = IsLeapYear(year);
		while (number > daytab[row][month]) {
			number -= daytab[row][month];
			month++;
		}
		day = number;
		printf("%04d-%02d-%02d\n", year, month, day);
	}
	return 0;
}

3.日期累加(北京理工大学)

1-2 暴力破解-模拟_第14张图片

评测系统

#include
#include
using namespace std;
int daytab[2][13] = {
	{0,31,28,31,30,31,30,31,31,30,31,30,31},//不是闰年
	{0,31,29,31,30,31,30,31,31,30,31,30,31},//是闰年
};
bool IsLeapYear(int year) {//是否闰年
	return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int NumberOfYear(int year) {//返回该年天数
	if (IsLeapYear(year)) {
		return 366;
	}
	else
		return 365;
}
int main() {
	int m = 0;
	cin >> m;
	int year, month, day,number;
	while (m--) {
		cin >> year >> month >> day >> number;
		int row = IsLeapYear(year);
		for (int j = 0; j < month; j++) {//加上今年已经过的天数
			number += daytab[row][j];
		}
		number += day;
		while (number > NumberOfYear(year)) {//确定年
			number -= NumberOfYear(year);
			year++;
		}
		month = 0;
		row = IsLeapYear(year);
		while (number > daytab[row][month]) {//确定月
			number -= daytab[row][month];
			month++;
		}
		day = number;//确定日
		printf("%04d-%02d-%02d\n", year, month, day);
	}
	return 0;
}

4.日期差值(上海交通大学)
1-2 暴力破解-模拟_第15张图片

评测系统

#include
#include
using namespace std;
int daytab[2][13] = {
	{0,31,28,31,30,31,30,31,31,30,31,30,31},//不是闰年
	{0,31,29,31,30,31,30,31,31,30,31,30,31},//是闰年
};
bool IsLeapYear(int year) {//是否闰年
	return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int NumberOfYear(int year) {//返回该年天数
	if (IsLeapYear(year)) {
		return 366;
	}
	else
		return 365;
}
int main() {
	string s1, s2;
	while (cin >> s1 >> s2) {
		int year1, month1, day1;
		int year2, month2, day2;
		int sum = 0;
		year1 = (s1[0] - 48) * 1000 + (s1[1] - 48) * 100 + (s1[2] - 48) * 10 + s1[3] - 48;
		year2 = (s2[0] - 48) * 1000 + (s2[1] - 48) * 100 + (s2[2] - 48) * 10 + s2[3] - 48;
		month1 = (s1[4] - 48) * 10 + s1[5] - 48;
		month2 = (s2[4] - 48) * 10 + s2[5] - 48;
		day1 = (s1[6] - 48) * 10 + s1[7] - 48;
		day2 = (s2[6] - 48) * 10 + s2[7] - 48;
		//处理中间年份
		for (int i = year1 + 1; i < year2; i++) {
			sum += NumberOfYear(i);
		}
		//处理两端年份
		if (month1 == month2) {
			if (day1 == day2) {
				sum += 0;
			}
			else {
				sum += abs(day1 - day2)+1;
			}
		}
		else {
			int row = IsLeapYear(year1);
			sum += daytab[row][month1] - day1 + 1;
			sum += day2;
			if (year1 == year2) {//没跨年,月份只会增大
				for (int i = month1 + 1; i < month2; i++) {
					sum += daytab[row][i];
				}
			}
			else {//跨年,分两段算
				for (int i = month1 + 1; i <= 12; i++) {
					sum += daytab[row][i];
				}
				for (int i = 1; i < month2; i++) {
					sum += daytab[row][i];
				}
			}
		}
		cout << sum << endl;
	}
}

5.Day of Week(上海交通大学)

1-2 暴力破解-模拟_第16张图片
评测系统

分析:
蔡勒公式
1.基本公式
日期≤1582年10月4日↓
在这里插入图片描述

日期>1582年10月4日↓
在这里插入图片描述
其中:
w是星期,w=0表示星期日,w=1表示星期一…
c是年份的前两位数
y是年份的后两位数
m是月份(一月m=13,二月m=14,三月m=3,四月m=4…十二月m=12)
当m=13或14时,年份要-1,即2003年变为2002年
如2002年2月5日
年份=2001
月份=14
日=5

也可采用 w=(day+2month+3(month+1)/5+year+year/4-year/100+year/400+1)%7
其中y为四位数的年份

#include
#include
#include
using namespace std;
int main() {
	string s;
	while (getline(cin,s)) {
		int i;
		int year, year2, month, day;
		int yearnum, monthnum, daynum;
		year = month = day = year2= 0;
		yearnum = monthnum = daynum = 0;
		for (i=0; ; i++) {
			if (s[i] == ' ')
				break;
			day = day * 10 + s[i]-48;
		}
		daynum = i - 1;
		
		string month2;
		for (i += 1; ; i++) {
			if (s[i] == ' ')
				break;
			month2 += s[i];
		}
		if (month2 == "January") {
			month = 1;
		}
		else if (month2 == "February") {
			month = 2;
		}
		else if (month2 == "March") {
			month = 3;
		}
		else if (month2 == "April") {
			month = 4;
		}
		else if (month2 == "May") {
			month = 5;
		}
		else if (month2 == "June") {
			month = 6;
		}
		else if (month2 == "July") {
			month = 7;
		}
		else if (month2 == "August") {
			month = 8;
		}
		else if (month2 == "September") {
			month = 9;
		}
		else if (month2 == "October") {
			month = 10;
		}
		else if (month2 == "November") {
			month = 11;
		}
		else {
			month = 12;
		}

		i += 1;
		year = (s[i]-48) * 10 + (s[i + 1]-48);
		year2 = (s[i + 2]-48) * 10 + (s[i + 3]-48);

		if (month == 1) {
			month = 13;
			if (year2 != 0)
				year2--;
			else
				year--;
		}		
		if (month == 2) {
			month = 14;
			if (year2 != 0)
				year2--;
			else
				year--;
		}
		int wee;
		if((year*100+year2<1582)||(year * 100 + year2==1582&&month<10)|| (year * 100 + year2 == 1582 && month == 10&&day<=4))
			wee = year2 + year2 / 4 + year / 4 - 2 * year + 26 * (month + 1) / 10 + day + 2;
		else
			wee = year2 + year2 / 4 + year / 4 - 2 * year + 26 * (month + 1) / 10 + day - 1;
		if (wee < 0) {
			wee = (wee % 7 + 7) % 7;
		}
		else
			wee = wee % 7;
		if (wee == 0) {
			cout << "Sunday" << endl;
		}
		else if (wee == 1) {
			cout << "Monday" << endl;
		}
		else if (wee == 2) {
			cout << "Tuesday" << endl;
		}
		else if (wee == 3) {
			cout << "Wednesday" << endl;
		}
		else if (wee == 4) {
			cout << "Thursday" << endl;
		}
		else if (wee == 5) {
			cout << "Friday" << endl;
		}
		else {
			cout << "Saturday" << endl;
		}
	}
	return 0;
}

6.日期类(北京理工大学)
1-2 暴力破解-模拟_第17张图片

评测系统

#include
#include
#include
using namespace std;
int main() {
	int a[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	int m = 0;
	cin >> m;
	while (m--) {
		int year, month, day;
		cin >> year >> month >> day;
		if (month == 12 && day == 31) {
			year++;
			day = 1;
			month = 1;
		}
		else if (day == a[month]) {
			month++;
			day = 1;
		}
		else {
			day++;
		}
		printf("%04d-%02d-%02d\n", year, month, day);
	}
}

三.其他模拟

1.剩下的树(清华大学)
1-2 暴力破解-模拟_第18张图片
测评系统

分析:
设置一个数组,在给定区间内就将数值设为1,最后统计1的个数

#include
#include
using namespace std;
int main() {
	int a[10005] = { 0 };
	int len=0, group = 0;
	cin >> len >> group;
	for (int k = 0; k < group; k++) {
		int m, n;
		cin >> m >> n;
		for (int i = m; i <= n; i++) {
			a[i] = 1;
		}
	}
	int sum = 0;
	for (int k = 0; k < len; k++) {
		if (a[k] == 1)
			sum++;
	}
	cout << len + 1 - sum;
}

2.手机键盘(清华大学)
1-2 暴力破解-模拟_第19张图片

评测系统

分析:
1-2 暴力破解-模拟_第20张图片

每一个字母需要的按键次数

1-2 暴力破解-模拟_第21张图片

int keytab[26] = { 1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4 };

判断两个字母是否位于同一个按键上
1-2 暴力破解-模拟_第22张图片
若在同一按键上,两个字母的差值=按键次数的差值
例如B-A=2-1=1
C-A=3-1=2

if (str[i] - str[i - 1] == keytab[str[i] - 'a'] - keytab[str[i - 1] - 'a']) {
	time += 2;
}

若不在同一按键上,两个字母的差值≠按键次数的差值
G-F≠1-3

完整代码

#include
#include
using namespace std;
int keytab[26] = { 1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,4,1,2,3,1,2,3,4 };
int main() {
	string str;
	while (cin >> str) {
		int time = 0;
		for (int i = 0; i < str.size(); i++) {
			time += keytab[str[i] - 'a'];//按键时间
			if (i != 0 && str[i] - str[i - 1] == keytab[str[i] - 'a'] - keytab[str[i - 1] - 'a']) {
				time += 2;
			}
		}
		cout << time << endl;
	}
	return 0;
}

3.XXX定律(浙江大学)
1-2 暴力破解-模拟_第23张图片
评测系统

#include
using namespace std;
int main() {
	int n = 0;
	while (cin>>n) {
		if (n == 0)
			break;
		int num = 0;
		while (n != 1) {
			if (n % 2 == 0) {
				n /= 2;
			}
			else {
				n = (3 * n + 1) / 2;
			}
			num++;
		}
		cout << num << endl;
	}
	return 0;
}

4.Grading(浙江大学)
1-2 暴力破解-模拟_第24张图片
评测系统

#include
using namespace std;
float max(float a, float b, float c) {
	if (a > b) {
		if (a > c) 
			return a;
		else
			return c;
	}
	else {
		if (b > c)
			return b;
		else
			return c;
	}
}
int main() {
	float P, T, G1, G2, G3, GJ;
	cin >> P >> T >> G1 >> G2 >> G3 >> GJ;
	if (abs(G2 - G1) <= T) {
		printf("%.1f", (G1 + G2) / 2);
	}
	else {
		if ((abs(G3 - G1) <= T && abs(G3 - G2) > T)) {
			printf("%.1f", (G3 + G1) / 2);
		}
		else if (abs(G3 - G1) > T && abs(G3 - G2) <= T) {
			printf("%.1f", (G3 + G2) / 2);
		}
		else if (abs(G3 - G1) <= T && abs(G3 - G2) <= T) {
			printf("%.1f", max(G1, G2, G3));
		}
		else {
			printf("%.1f", GJ);
		}
	}
}

你可能感兴趣的:(算法C/C++,c++,c语言,算法)