機試題練習(2019年-2014年)

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+2m+3(m+1)/5+y+y/4y/100+y/400+1) W= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7
在公式中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
佈局1

2 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(n2log2(n))O(n^2*log_2(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(nlog2(n))O(n*log_2(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;
}

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