nwpu复试上机题练习
2019年
1.排序@@
#include "iostream"
#include "set"
using namespace std;
int main(int argc, char* argv[])
{
set<int> st;
int n;
cin>>n;
while(n--){
for(int i = 0;i < 8;i++){
int num;
cin>>num;
st.insert(num);
}
for(auto num : st){
cout<<num<<" ";
}
cout<<endl;
}
return 0;
}
手动排序如下:
#include <bits/stdc++.h>
using namespace std;
ostream &operator<<(ostream &c, const vector<int> v)
{
for (auto i : v)
{
c << i << " ";
}
c << endl;
return c;
}
void insert_sort(vector<int> &v)
{//找到合适的位置 插入选中的元素
if (!v.size())
return;
for (int i = 1; i < v.size(); i++)
{
int k = i - 1, key = v[i];
while (k >= 0 and key < v[k])
{
v[k + 1] = v[k];
k--;
}
v[k + 1] = key;
}
return;
}
void select_sort(vector<int> &v)
{
if (!v.size())
return;
for (int i = 0; i < v.size() - 1; i++)
{//每轮选出最大的元素,放在已排序队列最右边
int min = i;
for (int j = i + 1; j < v.size(); j++)
{
if (v[j] < v[min])
min = j;
}
swap(v[min], v[i]);
}
}
void bubble_sort(vector<int> &v)
{ //把最大的元素放在最后面
for (int i = 0; i < v.size() - 1; i++)
{
for (int j = 0; j < v.size() - 1 - i; j++)
{
if (v[j] > v[j + 1])
swap(v[j], v[j + 1]);
}
}
return;
}
void quick_sort(vector<int> &s, int l, int r)
{
if (l < r)
{
int i = l, j = r, x = s[l];
while (i < j)
{
while(i < j && s[j] >= x) // 从右向左找第一个小于x的数
j--;
if(i < j)
s[i++] = s[j];
while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
i++;
if(i < j)
s[j--] = s[i];
}
s[i] = x;
quick_sort(s, l, i - 1); // 递归调用
quick_sort(s, i + 1, r);
}
}
int main()
{
vector<int> v({3, 4, 1, 2, 5});
bubble_sort(v);
cout << v;
cin.get();
}
2.求三角形面积
#include "iostream"
#include <iomanip>
#include "math.h"
using namespace std;
int main(int argc, char* argv[])
{
int n;
cin>>n;
while(n--){
double a,b,c;
cin>>a>>b>>c;
if(a+b>c && a+c>b && b+c>a){
double p = (a+b+c)/2;
cout<<fixed<<setprecision(2)<<sqrt(p*(p-a)*(p-b)*(p-c))<<endl;
}else{
cout<<"NaN"<<endl;
}
}
return 0;
}
3.判断IP地址是否有效
#include "iostream"
#include "stdio.h"
using namespace std;
bool check(int num){
return num>=0&&num<=255 ? 1 : 0;
}
int main(int argc, char* argv[])
{
int n;
cin>>n;
while(n--){
int a,b,c,d;
scanf("%d.%d.%d.%d",&a,&b,&c,&d);
if(check(a)&&check(b)&&check(c)&&check(d)){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
}
return 0;
}
4.求质数@
#include "iostream"
#include "math.h"
using namespace std;
bool isPrime(int n){
if(n <= 1) return 0;
if(n == 2) return 1;
for(int i = 2;i<=sqrt(n);i++){
if(n%i == 0) return 0;
}
return 1;
}
int main(int argc, char* argv[])
{
int m,n;
cin>>m>>n;
while(n){
if(isPrime(m)) {
cout<<m<<endl;
n--;
}
m++;
}
return 0;
}
5.一天中的任意两天差值
#include "iostream"
using namespace std;
int main(int argc, char* argv[])
{
int n;
cin>>n;
while(n--){
int year1,month1,day1,year2,month2,day2;
scanf("%d %d %d %d %d %d",&year1,&month1,&day1,&year2,&month2,&day2);
cout<<(month2-month1)*30+day2-day1+1<<endl;
}
return 0;
}
6.四则运算@@
思路:
- 首先设定符号的优先级,例如乘除法优先级高于加法高于减法。
- 再设定符号栈s和数字栈n,定义“调整”:弹出数字栈顶两个元素与符号栈顶一个运算符,进行运算,将运算结果压入数字栈。其实就是优先计算一个最基本的式子。
- 开始从左向右依次匹配:
- 遇到数字,首先完整解析出数字(如32.13),再压入数字栈n
- 遇到字符,如果符号栈顶字符优先级高且,调整符号栈;否则压入该字符
- 遇到左括号,找到对应的右括号,将递归调用自身处理它们包裹的字符串,得到对应的数值。将数值压入数字栈。指针指向刚才的右括号下一个元素,继续匹配。
- 匹配结束后符号栈如果不空,则进行调整直到栈空。最后数字栈必剩下一个数值,即为结果
#include <iostream>
#include <stack>
#include <iomanip>
#include <string>
using namespace std;
int prios(char c)
{
switch (c)
{
case '*':
return 3;
case '/':
return 2;
case '+':
return 1;
case '-':
return 0;
default:
return 0;
}
}
double matchNum(string s, int &p)
{
//匹配数字 并且移动p
string num = "";
while (isdigit(s[p]) or s[p] == '.')
{
num += s[p];
p++;
}
return stod(num);
}
void adjust(stack<char> &c, stack<double> &n)
{
double n1 = n.top();
n.pop();
double n2 = n.top();
n.pop();
double n3;
switch (c.top())
{
case '+':
n3 = n1 + n2;
break;
case '-':
n3 = n2 - n1;
break;
case '*':
n3 = n2 * n1;
break;
case '/':
n3 = n2 / n1;
break;
}
n.push(n3);
c.pop();
}
int findRight(int p, string s)
{
stack<char> st;
while (p <= s.size())
{
if (s[p] == '(')
st.push('(');
else if (s[p] == ')')
st.pop();
if (st.empty())
return p;
p++;
}
return -1;
}
double sum(string s)
{
stack<char> c;
stack<double> n;
int p = 0; //pos
while (p < s.size())
{
char ch = s[p];
if (isdigit(ch))
{
n.push(matchNum(s, p));
}
else if (ch == '*' or ch == '/' or ch == '+' or ch == '-')
{
if (!c.empty() and prios(ch) <= prios(c.top()))
{
adjust(c, n);
}
c.push(ch);
p++;
}
else if (ch == '(')
{
int index = findRight(p, s);
n.push(sum(s.substr(p + 1, index - p - 1)));
p = index + 1;
}
}
while (!c.empty())
{
adjust(c, n);
}
return n.top();
}
int main()
{
int n;
cin >> n;
cin.get();
while (n--)
{
string s;
getline(cin,s);
double ans = sum(s);
if(ans - (int)ans ==0){
cout<<(int)ans<<endl;
}else{
cout<<fixed<<setprecision(2)<<ans<<endl;
}
}
return 0;
重难点:
- 整体思路,特别是设定运算符优先级,规定两个栈的调整规则
- 23.123字符转数字的实现:stod字符串转double
if (isdigit(s[p])) //如果首字母是数字,就与后续数字拼成一个数
{
string num_s;
while (isdigit(s[p]) or s[p] == '.')
{
num_s += s[p++];
}
n.push(stod(num_s)); //223.221由string转为double
}
- 找到右括号并正确分隔字符串:string.substr方法,注意其第一个参数是起始位置,第二个参数是要分割的长度而不是结束位置。
else if (s[p] == '(')
{
int pos = findRight(p,s);
//pos这时候指向正确的对应右括号
string u(s);
n.push(sum(s.substr(p + 1, pos - p - 1)));
s = u;//字符串s已被破坏
p = pos + 1;
}
- 判断是否为整数并输出2位小数
if (ans - (int)ans == 0)
{ //是整数
cout << ans << endl;
}
else
{ //是小数
cout << fixed << setprecision(2) << ans << endl;
}
运行结果:输出了sum函数每次调用时传入的字符串,正确。
2018年
1.输出阶乘
#include <iostream>
using namespace std;
int factorial(int n){
int ans = 1;
for(int i = 1;i<=n;i++){
ans *= i;
}
return ans;
}
int main()
{
int N;
cin >> N;
while (N--)
{
int n;
cin >> n;
cout << factorial(n) << endl;
}
return 0;
}
2.n个数中取m个数
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int m,n;
cin>>m>>n;
int a=1,b=1;
for(int i = m;i > m-n;i--){
a *= i;
}
for(int i = 1;i <= n;i++){
b *= i;
}
cout<<a/b<<endl;
return 0;
}
3.字符串反转
要会用algorithm库的reverse函数。当然考试时须手写。
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string myReverse(string s)
{//有没有就地翻转的方法?
string t = "";
for (int i = s.size() - 1; i >= 0; i--)
{
t += s[i];
}
return t;
}
int main(int argc, char *argv[])
{
int n;
cin >> n;
cin.get();
while (n--)
{
string s;
getline(cin, s);
//reverse(s.begin(),s.end());
cout << myReverse(s) << endl;
}
return 0;
}
4.检测回文串
注意要cin.get吃回车字符,cin.getline才能接收到正确的字符串!
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main(int argc, char *argv[])
{
int n;
cin>>n;
cin.get();//吃回车字符
string s,s_old;
while(n--){
getline(cin,s);//输入带空格的字符串
s_old = s;
reverse(s.begin(),s.end());
if(s_old == s){
cout<<"yes"<<endl;
}else{
cout<<"no"<<endl;
}
}
return 0;
}
5.括号匹配@
这里要分为两个函数。子函数判断是否为匹配的括号串,返回0或1,主函数根据返回值输出yes或no。
//(([]))
#include <iostream>
#include <string>
#include <stack>
using namespace std;
bool check(string &s)
{
//cout<<s<<endl;
stack<char> st;
for (auto c : s)
{
switch (c)
{
case '{':
case '(':
case '[':
st.push(c);
break;
case '}':
if (st.empty() || st.top() != '{')
{
return 0;
}
st.pop();
break;
case ']':
if (st.empty() || st.top() != '[')
{
return 0;
}
st.pop();
break;
case ')':
if (st.empty() || st.top() != '(')
{
return 0;
}
st.pop();
break;
}
}
if (!st.empty())
{
return 0;
}
return 1;
}
int main(int argc, char *argv[])
{
int n;
cin >> n;
cin.get(); //吃回车字符
while (n--)
{
string s;
getline(cin, s); //输入带空格的字符串
if(check(s)){
cout<<"yes"<<endl;
}else{
cout<<"no"<<endl;
}
}
return 0;
}
6.美国时间(闰年问题)@@
思路:这题难在闰年的概念,如果不知道就做不出来
普通闰年:公历年份是4的倍数的,且不是100的倍数,为闰年。(如2004年就是闰年);
世纪闰年:公历年份是整百数的,必须是400的倍数才是世纪闰年(如1900年不是世纪闰年,2000年是世纪闰年);
闰年2月29,平年2月28
另外cout设置精度、month用数组存都是要记住的点。
#include <iostream>
using namespace std;
void myCout(int x1, int x2, int x3, int x4, int x5)
{
cout << x1 << " ";
cout.fill('0');
cout.width(2);
cout << x2 << " ";
cout.width(2);
cout << x3 << " ";
cout.width(2);
cout << x4 << " ";
cout << x5 << endl;
}
int main()
{
int month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int month2[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int n;
cin >> n;
cin.get();
while (n--)
{
int y, m, d, h, s;
cin >> y >> m >> d >> h >> s;
if (h >= 16)
{
myCout(y, m, d, h - 16, s);
}
else
{
if (d > 1)
{
myCout(y, m, d, h + 8, s);
}
else
{ //d=1
if (m > 1)
{
if (y % 4 == 0 and y % 100 != 0 or y % 400 == 0)
{ //闰年
myCout(y, m - 1, month2[m - 2], h + 8, s);
}
else
{ //平年
myCout(y, m - 1, month[m - 2], h + 8, s);
}
}
else
{ //m=1 d=1
myCout(y - 1, 12, 31, h + 8, s);
}
}
}
}
return 0;
}
运行结果:
7.二元一次方程求根@
设置精度要熟练。
#include <iostream>
#include <math.h>
#include <iomanip>
using namespace std;
int main()
{
int n;
cin >> n;
cin.get();
while (n--)
{
int a, b, c;
cin >> a >> b >> c;
int x = b * b - 4 * a * c;
if (x >= 0)
{ //有解
cout << fixed << setprecision(2) << double((-b + sqrt(x)) / (2 * a)) << " " << double((-b - sqrt(x)) / (2 * a)) << endl;
}
else
{ //无解
cout << "NaN" << endl;
}
}
return 0;
}
2017年
1.计算平均时间
#include <iostream>
using namespace std;
void func(int h1,int h2,int m1,int m2,int s1,int s2){
if(h1==0 and h2==11){
h1=12;
}else if(h2==0 and h1==11){
h2=12;
}
int sec = s1+m1*60+h1*3600 + s2+m2*60+h2*3600;
sec/=2;
int h=sec/3600;
int m=(sec%3600)/60;
int s=sec-3600*h-60*m;
cout<<h<<" "<<m<<" "<<s<<endl;
}
int main(){
int n=2;
while(n--){
int h1,h2,m1,m2,s1,s2;
cin>>h1>>m1>>s1>>h2>>m2>>s2;
func(h1,h2,m1,m2,s1,s2);
}
return 0;
}
2.排序
#include <iostream>
#include <vector>
#include <string>
using namespace std;
void bubble_sort(vector<int> &v){
for(int i=0;i<v.size();i++){
for(int j=0;j<v.size()-i-1;j++){
if(v[j+1]<v[j]) swap(v[j+1],v[j]);
}
}
}
int main(){
int n;
cin>>n;
while(n--){
vector<int> v;
int temp;
while (1)
{
cin>>temp;
v.push_back(temp);
//getchar()一般等于空格
if (getchar() == '\n') break;
}
bubble_sort(v);
for(auto i:v){
cout<<i<<" ";
}
cout<<endl;
}
return 0;
}
3.四则运算
前面做过一次,这里再做一次,力求减少编码时间和代码量。
(仍然用了1h左右&100行代码)
#include <iostream>
#include <string>
#include <stack>
#include <iomanip>
using namespace std;
int level(char c){
switch(c){
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}
void adjust(stack<double> &num,stack<char> &ch){
double high = num.top();
num.pop();
double low = num.top();
num.pop();
switch (ch.top()){
case '+':
num.push(high+low);
break;
case '-':
num.push(low-high);
break;
case '*':
num.push(high*low);
break;
case '/':
num.push(low/high);
break;
}
ch.pop();
}
int findRightBracket(int pos,string s){
stack<char> st;
for(int i = pos;i<s.size();i++){
if(s[i]=='('){
st.push('(');
}
else if(s[i]==')'){
//默认一定会匹配到左括号
st.pop();
}
if(st.empty()){
return i;
}
}
return -1;
}
double sum(string s){
stack<double> num;
stack<char> ch;
string thisNum;
int p = 0;
int nextp;
while(p<s.size()){
switch(s[p]){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
thisNum="";
thisNum+=s[p++];
while(isdigit(s[p]) or s[p]=='.'){
thisNum+=s[p++];
}
num.push(stod(thisNum));
break;
//停止时p指向运算符
case '*':
case '/':
case '+':
case '-':
if(!ch.empty() and level(s[p])<=level(ch.top())){
adjust(num,ch);
}
ch.push(s[p++]);
break;
case '(':
nextp= findRightBracket(p,s);
num.push(sum(s.substr(p+1,nextp-p-1)));
p = nextp+1;
break;
default:
break;
}
}
while(!ch.empty()){
adjust(num,ch);
}
cout<<s<<"="<<num.top()<<endl;
return num.top();
}
int main()
{
int n;
cin >> n;
cin.get();
while (n--)
{
string s;
getline(cin,s);
double ans = sum(s);
if(ans - (int)ans ==0){
cout<<(int)ans<<endl;
}else{
cout<<fixed<<setprecision(2)<<ans<<endl;
}
}
return 0;
}
4.括号匹配
#include <iostream>
#include <string>
#include <stack>
using namespace std;
int check(string s)
{
stack<char> st;
for (auto i : s)
{
switch (i)
{
//这里的case好像不能再简写了
case '(':
case '[':
case '{':
st.push(i);
break;
case ')':
if (st.top() == '(')
{
st.pop();
}
else
{
return 0;
}
break;
case ']':
case '}':
if (st.top() == char(i - 2))
{
st.pop();
}
else
{
return 0;
break;
}
}
}
if (st.empty())
{
return 1;
}
else
{
return 0;
}
}
int main()
{
int n;
cin >> n;
cin.get();
while (n--)
{
string s;
getline(cin, s);
if (check(s))
{
cout << "yes" << endl;
}
else
{
cout << "no" << endl;
}
}
return 0;
}
5.判断今天星期几
可以看看这篇文章
其中基姆拉尔森计算公式:
W
=
(
d
+
2
∗
m
+
3
∗
(
m
+
1
)
/
5
+
y
+
y
/
4
−
y
/
100
+
y
/
400
+
1
)
W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7
W=(d+2∗m+3∗(m+1)/5+y+y/4−y/100+y/400+1)
在公式中d表示日期中的日数,m表示月份数,y表示年数。
注意:在公式中有个与其他公式不同的地方:
把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算。
考试时不给公式是做不出来的。
6.串的模式匹配
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
int cnt = 0;
string s0;
cin >> s0;
ifstream file;
file.open(R"(H://1.txt)", ios::in);
if (!file.is_open())
{
cout << "error file";
return -1;
}
while (file.good())
{
string s;
getline(file, s, ' ');
auto pos = s.find(',');
if (pos != string::npos)
{
if (s.substr(0, pos) == s0 or s.substr(pos + 1, s.size() - pos - 1); == s0)
//注意substr函数的用法
cnt++;
}
else
{
if (s == s0)
cnt++;
}
}
file.close();//记得关闭文件
cout << cnt << endl;
return 0;
}
BUAA2017年
1. 求中位数位置@@@
一, 求中位数的位置
先输入一个整型数字N,接着输入n个无序的数字。要求输入升序排列后的中位数,以及该中位数输入时的次序。如果N为偶数,则输出有两个中位数;如果N为奇数,输出最中间的数字即可。
Example1:
Input: 5
9 2 7 1 6
Output:
6 5
Example2:
Input:6
9 6 7 1 2 3
Output:
3 6
6 2
此题要注意:
1. 本题要求记录输入时的序号,所以需要自定义数据结构放在vector容器里
2. 要熟练写出快排(而不是用STL的排序)
#include <iostream>
#include <vector>
using namespace std;
typedef struct number
{
int num;
int pos;
} Number;
void quick_sort(vector<Number> &v, int left, int right)
{
if (left >= right)
return;
int i = left;
int j = right;
Number tmp = v[i];
while (i < j)
{
while (v[j].num > tmp.num and i < j)
{
j--;
}
v[i] = v[j];
while (v[i].num < tmp.num and i < j)
{
i++;
}
v[j] = v[i];
}
v[i] = tmp;
quick_sort(v, left, i - 1);
quick_sort(v, i + 1, right);
}
int main()
{
int n;
cin >> n;
vector<Number> vc(n);
for (int i = 0; i < n; i++)
{
int x;
cin >> x;
vc[i].num = x, vc[i].pos = i + 1;
}
for (auto i : vc)
quick_sort(vc, 0, n - 1);
if (n % 2 == 0)
{
cout << vc[n / 2 - 1].num << " " << vc[n / 2 - 1].pos << endl
<< vc[n / 2].num << " " << vc[n / 2].pos << endl;
}
else
{
cout << vc[(n - 1) / 2].num << " " << vc[(n - 1) / 2].pos << endl;
}
return 0;
}
2016年
1.求平均跑步时间
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
cin.get();
while (n--)
{
int m,s,ms;
int m0=0,s0=0,ms0=0;
int cnt = 3;
while(cnt--){
cin>>m>>s>>ms;
m0+=m,s0+=s,ms0+=ms;
}
m0/=3,s0/=3,ms0/=3;
cout<<m0<<" "<<s0<<" "<<ms0<<endl;
}
return 0;
}
2015年
1.十进制转二进制
#include <iostream>
#include <string>
#include<algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
string s="";
while(n){
char c = n%2+'0';
s+=c;
n/=2;
}
reverse(s.begin(),s.end());
cout<<s<<endl;
return 0;
}
2.迷宫
#include <bits/stdc++.h>
using namespace std;
bool checkPos(int x, int y, int N)
{
return x >= 0 and y >= 0 and x < N and y < N;
}
int main()
{
int N;
cin >> N;
array<int, 2> pos;
cin >> pos[0] >> pos[1];
char i; //指令
cin >> i;
switch (i)
{
case 'w':
pos[0]--;
break;
case 'a':
pos[1]--;
break;
case 's':
pos[0]++;
break;
case 'd':
pos[1]++;
break;
}
if(checkPos(pos[0],pos[1],N)){
cout<<"Y";
}else{
cout<<"N";
}
cin.get();
cin.get();
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main()
{
int N;
cin >> N;
bool b[N][N]; //棋盘
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
cin >> b[i][j];
}
cin.get(); //吃回车
}
int x, y;
cin >> x >> y;
char i; //指令
cin >> i;
switch (i)
{
case '3':
x--;
break;
case '0':
y--;
break;
case '1':
x++;
break;
case '2':
y++;
break;
}
if (x >= 0 and y >= 0 and x < N and y < N and b[x][y] == 0)
{
cout << "Y";
}
else
{
cout << "N";
}
cin.get();
cin.get();
return 0;
}
3.字符串替换@@@
#include <bits/stdc++.h>
using namespace std;
int main()
{
string a, b, c;
getline(cin, a);
getline(cin, b);
getline(cin, c);
auto pos = a.find(b);
if (pos != string::npos)
{
//用c替换a中从pos开始(包括0)的n个字符的子串
a.replace(pos,b.size(),c);
cout<<a;
}
else
{
cout << a;
}
cin.get();
cin.get();
return 0;
}
5.1045六数码问题(经典BFS)@@@
现有一两行三列的表格如下: A B C D E F
把1、2、3、4、5、6六个数字分别填入A、B、C、D、E、F格子中,每个格子一个数字且各不相同。每种不同的填法称为一种布局。如下:
1 3 5
2 4 6
布局12 5 6
4 3 1
布局2定义α变换如下:把A格中的数字放入B格,把B格中的数字放入E格,把E格中的数字放入D格,把D格中的数字放入A格。
定义β变换如下:把B格中的数字放入C格,把C格中的数字放入F格,把F格中的数字放入E格,把E格中的数字放入B格。问:对于给定的布局,可否通过有限次的α变换和β变换变成下面的目标布局:
1 2 3
4 5 6输入
本题有多个测例,每行一个,以EOF为输入结束标志。每个测例的输入是1到6这六个数字的一个排列,空格隔开,表示初始布局ABCDEF格中依次填入的数字。
输出
每个输出占一行。可以转换的,打印Yes;不可以转换的,打印No。
第二遍做 ,还是用了好久,/(ㄒoㄒ)/~~
BFS和字符数组与数值之间的转换不熟悉。
#include <iostream>
#include <string>
#include <math.h>
#include <queue>
#include <cmath>
using namespace std;
int alpha(int n){
char x[7];
//itoa(n,x,10);
sprintf(x,"%d",n);
char tmp= x[0];
x[0]=x[3],x[3]=x[4],x[4]=x[1],x[1]=tmp;
int ans;
sscanf(x,"%d",&ans);
return ans;
}
int beta(int n){
char x[7];
//itoa(n,x,10);
sprintf(x,"%d",n);
char tmp= x[1];
x[1]=x[4],x[4]=x[5],x[5]=x[2],x[2]=tmp;
int ans;
sscanf(x,"%d",&ans);
return ans;
}
int cnt=0;
void bfs(queue<int> qu){
int size = qu.size();//要记录size
for(int i=0;i<size;i++){
int num = qu.front();
if(num==123456) return;
qu.pop();
qu.push(alpha(num));
qu.push(beta(num));
}
cnt++;
bfs(qu);
}
int func(int n){
queue<int> qu;
qu.push(n);
bfs(qu);
return cnt;
}
int main()
{
int n;
cin >> n;
while(n--){
int x1,x2,x3,x4,x5,x6;
cin>>x1>>x2>>x3>>x4>>x5>>x6;
cout<<func(x1*100000+x2*10000+x3*1000+x4*100+x5*10+x6)<<endl;
cnt=0;
}
return 0;
}
6.1422.输出命题公式的真值表@
先输入一个正整数n(n小于等于10),表示共有n个命题变元,再输入一个类似于逆波兰表达式的字符串表示一个命题公式,约定在该字符串中用一位的十进制数表示一个命题变元,用a、o、n、i、e分别表示且、或、非、蕴含、等值,用类似于逆波兰表达式形式的字符串表示的命题公式的真值表波兰表达式(即二元运算,两个操作数在前,运算符在后;一元运算,一个操作数在前,运算符在后)。
输入 先输入一个小于等于10的正整数n,再输入一个字符串。
输出
输出该字符串表示的命题公式的真值表。 提示: 如果用P、Q、R分别表示这三个命题变元的话,
输入数据01a2i表示的命题公式是:((P∧Q)→R) 输入数据012ia表示的命题公式是:(P∧(Q→R))
输入数据0n表示的命题公式是:┐P输入样例 3 01a2i 输出样例 0 0 0 1 0 0 1 1 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1 1 1
0 0 1 1 1 1
想了好久,逻辑要清楚,一步一步写代码,一步一步测试。。
#include <bits/stdc++.h>
using namespace std;
string itode(int n, int len)
{
string s = "";
while (n)
{
s += (n % 2 + '0');
n /= 2;
}
while (s.size() < len)
{
s += '0';
}
reverse(s.begin(), s.end());
return s;
}
ostream &operator<<(ostream &out, stack<bool> s)
{
while (not s.empty())
{
out << s.top() << " ";
s.pop();
}
out << endl;
return out;
}
bool sum(string s)
{ //s=00a1i
stack<bool> num;
for (auto i : s)
{
if (isdigit(i))
{
num.push(i - '0');
}
else
{
bool first, second;
second = num.top();
num.pop();
if (i == 'n') //单值运算符特殊处理
{
num.push(!second);
continue;
}
first = num.top();
num.pop();
switch (i)
{
case 'a':
num.push(first & second);
break;
case 'o':
num.push(first | second);
break;
case 'i': //注意蕴涵怎么实现的
num.push(!first | second);
break;
case 'e':
num.push(first == second);
break;
}
}
}
return num.top();
}
int main()
{
int n;
cin >> n;
cin.get();
string s;
getline(cin, s);
// 思路:记住符号的位置,再生成000串,在指定位置插入
// 1.记录符号的位置
char a[11];
for (int i = 0; i < 11; i++)
{
a[i] = '*';
}
for (int i = 0; i < s.size(); i++)
{
if (isalpha(s[i]))
{
a[i] = s[i];
}
}
// 2.生成000 001这些串 并插入符号
for (int i = 0; i < pow(2, n); i++)
{
s = itode(i, n);
for (int j = 0; j < 11; j++)
{
if (a[j] != '*')
{
string in = "";
in += a[j];
s.insert(j, in);
}
}
for (auto i : s)
{
if (isdigit(i))
{
cout << i << " ";
}
}
cout << sum(s) << endl;
}
system("pause");
return 0;
}
7.1441连阴雨(经典DFS)@@@
因为下雨,地上有很多水,W代表积水,.代表干燥,我们将“相邻”定位为八个方向,相邻的积水构成一个水坑,先输入M,N,再输入一个M行N列字符矩阵,输出互不相邻的水坑个数。
输入:
10 12
W…WW.
.WWW…WWW
…WW…WW.
…WW.
…W…
…W…W…
.W.W…WW.
W.W.W…W.
.W.W…W.
…W…W.输出
3
一开始我的思路:map中需要一位表示脏位,从um中选第一个点,遍历可接近的点并标记,全都标记为完了还没路走 count++,然后选第二个点继续。数据结构用unordered_map<array<int, 2>, bool, arrayHash> um
没做出来,看答案才知道要用dfs:
重做第二遍,走方向的时候出了bug调试了会
#include <iostream>
#include <vector>
using namespace std;
int cnt = 0;
vector<string> b; //棋盘
void dfs(int x, int y)
{
//检查(x,y)坐标点的数据
//先检查点是否合法
if (x < 0 or x >= b.size() or y < 0 or y >= b[0].size() - 1 or b[x][y] == 'X' or b[x][y] == '.')
return;
b[x][y] = 'X'; //标记此点
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
//往8个方向走
dfs(x + i, y + j);
}
}
}
int main()
{
int n, m;
cin >> n >> m;
cin.get();
while (n--)
{
string s;
getline(cin, s);
b.push_back(s);
}
for (int i = 0; i < b.size(); i++)
{
for (int j = 0; j < m; j++)
{
if (b[i][j] == 'W')
{
//初始等于W的 一圈内全变为X
cnt++;
dfs(i, j);
}
}
}
cout << cnt << endl;
return 0;
}
运行结果:
2014年
1.猴子挖花生
问题描述:在二维直角平面坐标系内,存在n堆花生,一只猴子位于原点,猴子要按顺序拿到所有的花生,并回到原点。猴子每次只能沿x或y方向移动一个单位。
输入:一个整数n(0<n<100),接下来的n行,每行两个整数,代表每堆花生的坐标。 输出:猴子走过的路程。
(printf("%d\n",d)输出) 输入样例:4
1 1
1 -1
-1 -1
-1 1
输出样例:10
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
int sum = 0;
cin >> n;
for (int i = 0; i < n; i++)
{
int x, y;
int x2, y2;
cin >> x >> y;
if (i == 0)
{
sum += (abs(x) + abs(y));
x2 = x, y2 = y;
continue;
}
sum += (abs(x - x2) + abs(y - y2));
x2 = x, y2 = y;
if (i == n - 1)
sum += (abs(x2) + abs(y2));
}
cout << sum << endl;
system("pause");
return 0;
}
2.1209滑雪@@
描述
Michael喜欢滑雪这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-…-3-2-1更长。事实上,这是最长的一条。
输入
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
输出
输出最长区域的长度。
输入样例
5 5
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
输出样例
25
一开始我是用暴力法做的,由于不一定从数值最大的点往下走就是最大路径,我就从所有点当起点走开始,找里面的最大值。规模大了肯定超时。时间复杂度
O
(
n
2
∗
l
o
g
2
(
n
)
)
O(n^2*log_2(n))
O(n2∗log2(n))
#include <bits/stdc++.h>
using namespace std;
int b[101][101];
int level = 0;
int m, n;
void myInsert(map<int, array<int, 2>> &map, int x, int y, int num)
{
if (x < 0 or y < 0 or x >= m or y >= n or b[x][y] > num)
return;
map.insert({b[x][y], {x, y}});
}
void dfs(int x, int y)
{
level++;
map<int, array<int, 2>> m;
myInsert(m, x + 1, y, b[x][y]);
myInsert(m, x - 1, y, b[x][y]);
myInsert(m, x, y + 1, b[x][y]);
myInsert(m, x, y - 1, b[x][y]);
if (m.empty()) //什么也没插进去 说明到底了
return;
int x0 = (*m.rbegin()).second[0]; //取出第一个元素
int y0 = (*m.rbegin()).second[1];
m.erase(m.begin(), m.end()); //清空map
//cout << x0 << " " << y0 << "-> " << b[x0][y0] << endl;
dfs(x0, y0);
}
int main()
{
cin >> m >> n;
int max = -1;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cin >> b[i][j];
}
}
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
dfs(i, j);
level > max ? max = level : max = max;
level = 0;
}
}
cout << max << endl;
system("pause");
return 0;
}
由于有非常多的重复状态,要考虑下DP,核心就是该点能走的步数等于邻近小于该点值的点能走的步数+1。
- 思路:
假设1-25每个数不重复出现,并出现一次
1.排序,先找到数值为1的点,dp该点值为1
2.找到数值为2的点,dp该点的值为dp[1]+1
3.找到数值为i的点,dp[i]=dp[附近最大值的点]+1 - 要实现的函数:
findNext(int x)给出数值为x的点,返回附近能滑坡的最大值 - 状态方程为
dp[x] = dp[findNext(x)] + 1;
- 时间复杂度 O ( n ∗ l o g 2 ( n ) ) O(n*log_2(n)) O(n∗log2(n))
#include <bits/stdc++.h>
using namespace std;
int m, n;
int b[101][101];
map<int, array<int, 2>> mp; //升序排列
int myFind(int x, int y, int num)
{
if (x < 0 or y < 0 or x >= m or y >= n or b[x][y] > num)
return -1;
return b[x][y];
}
int findNext(int key)
{
int x = mp[key][0];
int y = mp[key][1];
set<int, greater<int>> res;
res.insert(myFind(x, y + 1, b[x][y]));
res.insert(myFind(x, y - 1, b[x][y]));
res.insert(myFind(x + 1, y, b[x][y]));
res.insert(myFind(x - 1, y, b[x][y]));
return *res.begin();
}
int main()
{
cin >> m >> n;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
cin >> b[i][j];
mp.insert({b[i][j], {i, j}});
}
}
int max = -1;
int dp[10001];
for (auto i : mp)
{
if (i.first == 1)
{
dp[1] = 1;
max = 1; //如果只有一个数据 要正确返回1
continue;
}
dp[i.first] = dp[findNext(i.first)] + 1;
dp[i.first] > max ? max = dp[i.first] : NULL;
//cout<<"dp["<<i.first<<"] = "<<dp[i.first]<<endl;
}
cout << max << endl;
system("pause");
return 0;
}
以上代码应该有能改进的地方,比如一定需要map存数值-点这种数据结构吗?本题也没说清楚每个点是不是出现且只出现一次。
3.1090用筛法求素数
求【a,b】之间的素数(除了1和他本身 再也没有其他数能将它整除)
#include <bits/stdc++.h>
using namespace std;
bool isPrime(int x)
{
for (int i = 2; i <= sqrt(x); i++)
{
if (x % i == 0)
return 0;
}
return 1;
}
int main()
{
int a, b;
cin >> a >> b;
for (int i = a; i <= b; i++)
{
if (isPrime(i))
cout << i << endl;
}
system("pause");
return 0;
}
4.1147木乃伊迷宫
描述
木乃伊地下宫殿是一个6行6列的迷宫。作为敢到木乃伊地下宫殿里去探险的你,有没有跟木乃伊抓迷藏的心理准备呵!游戏在木乃伊所在的迷宫里展开,任务就是尽快赶到出口。你一次只能走一步,而木乃伊可以走两步,但木乃伊是很笨的,他总是先尽量跟你达到同一列,如果已经是同一列了,他才会像你走来,有墙的地方人和木乃伊都不能过,你可以利用障碍物牵制住木乃伊。
输入
先输入墙的数量n,然后在后续的n行里每行有3个数表示一堵墙,3个数分别为格子的行、列和墙的位置(0表示这个格子的下方是墙,1表示这个格子的右方是墙),再下来的3行每行2个数,分别表示木乃伊、人还有出口的位置。
输出
如果能安全逃生则输出Yes,否则输出No,答案占一行。
输入样例
5
0 0 0
1 1 1
1 4 1
3 4 1
4 3 0
3 3
3 1
5 5
输出样例
No
这题我选择死亡!挖个巨坑吧。
我的代码后面死循环了,就是木乃伊被卡住的时候,人反复横跳无限循环。这个时候应该禁止反复横跳。
找了一篇大佬的题解,还没看
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
ostream &operator<<(ostream& c,char b[6][6]){
for(int i=0;i<6;i++){
for(int j=0;j<6;j++){
c<<b[i][j]<<" ";
}
cout<<endl;
}
return c;
}
char b[6][6];
int mx,my,rx,ry,cx,cy;
bool check_if_err(int rx,int ry){
return rx<0 or ry<0 or rx>=6 or ry>=6 or b[rx][ry]=='X';
}
int dfs(int rx,int ry){
cout<<b<<endl;
if((abs(ry-my) + abs(rx-mx))<=1 ) return 0;
if(rx==cx and ry==cy) return 1;
for(int i=-1;i<=1 ;i++){
for(int j=-1;j<=1 ;j++){
if(abs(i+j)==1){//只能走上下左右四个方向
if(!check_if_err(rx+i,ry+j)){
//人能走了
b[rx+i][ry+j]='R';
b[rx][ry]='O';
b[mx][my]='O';
//判断木乃伊怎么走
int distancey = my-(ry+j);//y轴的距离
int distancex = mx-(rx+i);//x轴的距离
if(distancey>=2) {
if(b[mx][my-1]=='X'){}
else if(b[mx][my-2]=='X'){
my-=1;
}else{
my-=2;
}
}
else if(distancey==1){
if(b[mx][my-1]!='X'){//有墙不能走
my-=1;//没墙走一格
if(distancex>=1) {
if(b[mx-1][my]!='X') mx-=1;
}
else if(distancex==0) return 0;
else {
if(b[mx+1][my]!='X') mx+=1;
}
}
}else if(distancey==0){
if(distancex>=2) {
if(b[mx-1][my]=='X'){}
else if(b[mx-2][my]=='X'){
mx-=1;
}else{
mx-=2;
}
}
else if(abs(distancex)<=1) return 0;
else {
if(b[mx+1][my]=='X'){}
else if(b[mx+2][my]=='X'){
mx+=1;
}else{
mx+=2;
}
}
}else if(distancey==-1){
if(b[mx][my+1]!='X'){//有墙不能走
my+=1;//没墙走一格
if(distancex>=1) {
if(b[mx-1][my]!='X') mx-=1;
}
else if(distancex==0) return 0;
else {
if(b[mx+1][my]!='X') mx+=1;
}
}
}else{
if(b[mx][my+1]=='X'){}
else if(b[mx][my+2]=='X'){
my+=1;
}else{
my+=2;
}
}
b[mx][my]='M';
dfs(rx+i,ry+j);//有一条路能走通
}
}
}
}
}
int main()
{
memset(b,'O',sizeof(b));
int n;
cin >> n;
while(n--){
int x,y,p;
cin>>x>>y>>p;
if(p==1){
b[x][y+1]='X';
}else if(p==0){
b[x+1][y]='X';
}
}
cin>>mx>>my;
b[mx][my]='M';//木乃伊
cin>>rx>>ry;
b[rx][ry]='R';//人
cin>>cx>>cy;
b[cx][cy]='C';//出口
//输入完毕,检查无误
dfs(rx,ry);
//cout<<b;
return 0;
}