【反思与总结---2】在线OJ②

欧几里得放蛋糕、字符型转为整数型

题目要求:

<1>.有W.H长和宽的网格,一个格子可以放一个蛋糕
<2>.但是任意两块蛋糕的欧几里得距离不能等于2
<3>.对于两个格子坐标(x1,y1),(x2,y2)的欧几里得距离为:( (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) ) 的算术平方根
<4>.输入网格长宽w和h(1~1000)
<5>.输出可以放的蛋糕数

解题思路:

<1>.构建一个二维数组,一开始全部置为1
<2>.不可以放蛋糕的地方置为0
<3>.遍历数组中1的个数,就是放蛋糕的数量
<4>.输出count

代码示例:

#include <iostream>

using namespace std;

int main()
{
	int W;
	int H;
	cin >> W;
	cin >> H;
	
	int array[1000][1000];

	for (int i = 0; i < W; ++i)
	{
		for (int j = 0; j < H; ++j)
		{
			array[i][j] = 1;
		}
	}

	int count = 0;

	for (int i = 0; i < W ; ++i)
	{
		for (int j = 0; j < H ; ++j)
		{
			if (array[i][j] == 1)
			{
				count++;

				if ((i + 2) < W)
				{
					array[i + 2][j] = 0;
				}
				if ((j + 2) < H)
				{
					array[i][j + 2] = 0;
				}
			}
		}
	}

	cout << count << endl;

	system("pause");
	return 0;
}

vs中使用int array[1000][1000]会直接段错误,牛客网也偶尔会,但是Linux不会…

所以还是优先使用vector的好…避免空间浪费而且简单…

题目要求:

<1>.输入字符串,把字符串转换为整数
<2>.要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
<3>.输入一个字符串,包括数字字母符号,可以为空
<4>.如果是合法的数值表达则返回该数字,否则返回0

解题思路:

<1>.首先判断是否为空船,空就直接返回0,然后判断正负号,确定最后返回的是正数还是负数
<2>.如果不是0-9的字母就不管,是0-9的就转换
<3>.if(str[i]<=‘0’||str[i]>=‘9’)
<4>.转换方法为res=res*10+str[i]-‘0’;
<5>.乘10是为了把之前的变为更高位,str[i]是当前位的数字,减’0’是为了转为数字
<6>.最后输出res

代码示例:

#include <iostream>
#include <string>

using namespace std;

int StrToInt(string str)
{
	if (str.empty())
	{
		return 0;
	}

	int flag = 1;

	if (str[0] == '+')
	{
		flag = 1;
		str[0] = '0';
	}
	else if (str[0] = '-')
	{
		flag = -1;
		str[0] = '0';
	}

	int res = 0;

	for (int i = 0; i < str.length(); ++i)
	{
		if (str[i] <= '0' || str[i] >= '9')
		{
			res = 0;
		}

		res = res * 10 + str[i] - '0';
	}

	return flag*res;
}

int main()
{
	string s1;

	getline(cin, s1);

	cout << StrToInt(s1)<<endl;

	system("pause");
	return 0;
}

反思:

<1>.一定要把题意弄清楚,才能写代码
<2>.直接把静态二维数组修改成vector的二维数组
<3>.修改不能放蛋糕的位置元素为0需要在count++的if条件中

正确代码示例:

#include<iostream>
#include<vector>

using namespace std;

int main()
{
    long W,H;
    cin>>W>>H;
    
    vector<vector<int>> vv;
    
    vv.resize(W);
    
    for(auto& e:vv)
    {
        e.resize(H,1);
    }
    
    int count=0;
    
    for(int i=0;i<W;++i)
    {
        for(int j=0;j<H;++j)
        {
            if(vv[i][j]==1)
            {
                count++;
                
                if((i+2)<W)
                {
                    vv[i+2][j]=0;
                }
            
                if((j+2)<H)
                {
                    vv[i][j+2]=0;
                }
            }
        }
    }
    
    cout<<count<<endl;
    
    return 0;
}

斐波那契数列、括号合法性判断

题目要求:

<1>.输入一个整数N(1-1000000),求出将其变为斐波那契数的最小步数
<2>.输出需要的步数

解题思路:

<1>.创建一个循环,不断生成斐波那契数,将之为其比较
<2>.找到第一个大于那个斐波那契数,sep1=n-f(i)
<3>.往后找到小于的那个斐波那契数,sep2=f(i)-n
<4>.比较sep1和sep2的值,输出较小的那个
<5>.斐波那契数列使用循环写法,不然会导致堆栈溢出

代码示例:

#include<iostream>

int fib(int n)
{
    int last2=1;
    int last3=1;
    int a=0;

    if(n==1||n==2)
    {
        return 1;
    }
    
    for(int i=3;i<n;++i)
    {
        a=last3+last2;
        last3=last2;
        last2=a;
    }
    return a;
}

int main()
{
    long long n;
    cin>>n;

    int sep1=0;
    int sep2=0;

    while(1)
    {
        if(n>fib(i))
        {
            sep1=n-fib(i);
        }
        if(n<fib(i+1))
        {
            sep2=fib(i+1)-n;
        }
    }

    if(sep1<sep2)
    {
        cout<<sep1<<endl;
    }
    else
    {
        cout<<sep2<<endl;
    }

    return 0;
}

题目要求:

<1>.给定一个字符串A和它的长度n,判断其是否为一个合法的括号串
<2>.不可以带字母

解题思路:

<1>.测试样例居然只给了(),并没有涉及到[]和{}
<2>.我全都写完居然每次都是堆栈溢出,但是vs没有段错误,可以满足要求
<3>.用stack为什么不行呢?参考了一下别人的用string的可以
<4>.所以这个题思路是借鉴别人的
<5>.用一个B拷贝A,把B逆置,然后逐个对比
<6>.if((A[i] == ‘(’ && B[i] == ‘)’) || (A[i] == ‘)’ && B[i] == ‘(’) || (A[i] == ‘(’ && B[i] == ‘(’) ||(A[i] == ‘)’&& B[i]==’)’))
<7>.循环走完return true,else中return false;

代码示例:

class Parenthesis
{
    public:
        bool chkParenthesis(string A,int n)
        {
            if(n%2!=0)
            {
                return false;
            }

            string B(A);
            reverse.(B.begin(),B.end());

            for(int i=0;i<n;++i)
            {
                if((A[i]=='('&& B[i]==')')|| (A[i]==')'&& B[i]=='(')||
                (A[i]=='('&& B[i]=='(')||(A[i]==')'&& B[i]==')'))
                {
                    continue;
                }
                return false;
            }
            return true;
        }
};

反思:

设变量已正确定义,以下不能统计出一行中输入字符个数(不包含回车符)的程序段是(D)

A n=0;while(ch=getchar()!='\n')n++;
B n=0;while(getchar()!='\n')n++;
C for(n=0;getchar()!='\n';n++);
D n=0;for(ch=getchar();ch!='\n';n++);

D只获取了一次字符串

有如下类模板定义:()

template<class T> class BigNumber{ 
    long n; 
public: 
    BigNumber(T i):n(i){}
    BigNumber operator+(BigNumber b)
    { 
        return BigNumber(n+b.n); 
    } 
};
已知b1,b2是BigNumber的两个对象,则下列表达式中错误的是(D)
3+3
b1+3
b1+b2
3+b1

此题考查的正是C++的运算符重载,+号被重载后相当于该类的一个成员函数了,出现该类对象(b1+)这种就是调用重载函数,+号后面的3或者b2就是参数,如果是3的话就会执行类型转化,将3变为BigNumber类型传给形参。至于D选项的错误我个人理解为+号左右两边的类型不匹配,3不是BigNumber的对象,调用+号的重载会编译失败

void main()
{
	int a=1,b=0,c=-1,d=0;
	d=++a||++b&&++c;
	cout<<d<<endl;
	return;
}

d=++a||++b&&++c中,++a||++b&&++c为逻辑表达式,其值要么为1,要么为0;

&& 运算符优先级高于 ||,所以最后算的是 || ,只要其中一个为真,表达式为真,表达式(++a)为2,不为0,为真,故d = 1;

假定一个类的构造函数为A(int aa,int bb){a=aa--;b=a*bb;},
		
则执行A x(4,5);语句后,x.a和x.b的值分别为(D)

A 205
B 315
C 54
D 420

a = aa–就是a = aa;aa–;这样的。所以a = 4,aa = 3之后b = a * bb=4 * 5 = 20;

评估报告里代码风格变成良了,代码规范也变成良了…要多注意…

正确代码示例:

#include<iostream>

using namespace std;

int main()
{
	int sep1 = 0;
	int sep2 = 0;
	int f0 = 0;
	int f1 = 1;
	int f = 0;

	int n;
	while(cin >> n)
    {
        while (1)
	    {
            f = f0 + f1;
            f0 = f1;
            f1 = f;

            if (f < n)
            {
                sep1 = n - f;
            }
            else
            {
                sep2 = f - n;
                break;
            }
        }

        if (sep1 < sep2)
        {
            cout << sep1 << endl;
        }
        else
        {
            cout << sep2 << endl;
        }
    }
    system("pause");
	return 0;
}

<1>.遍历的是字符串,放进的是栈
<2>.对switch case语句用得太少,熟练度不够

class Parenthesis 
{
public:
    bool chkParenthesis(string A, int n) 
    {
        stack<char> v;
        
        for(auto e:A)
        {
            switch(e)
            {
                case '(':v.push(e);break;
                case ')':
                    if(v.empty()||v.top()!='(')
                    {
                        return false;
                    }
                    else
                    {
                        v.pop();
                    }
                    break;
                default:return false;break;
            }
        }
        return true;
    }
};

判断字符串是否满足两种排序、求最小公倍数

题目要求:

<1>.考拉忙着吃树叶,所以我们来帮忙判断字符串满不满足两种排序
<2>.输入一个整数,表示有多少个字符串,然后输入字符串
<3>.满足字典序,但不满足长度排序输出lexi…什么的
<4>.满足长度排序,但不满足字典序,输出lengths
<5>.既不满足长度也不满足字典序,输出none
<6>.既满足长度也满足字典序,输出both

解题思路:

<1>.创建一个vector v(n)
<2>.写出两种排序的检测算法
<3>.输入字符串的时候用cin就好,用getline是错的,v[0]位置放不进去
<4>.根据题目要求,进行输出

代码示例:

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

using namespace std;

bool CheckLength(vector<string> v,int n)
{
    for(int i=1;i<n;++i)
    {
        if(v[i-1].length()<v[i].length())
        {
            continue;
        }
        return false;
    }
    return true;
}

bool CheckDic(vector<string> v,int n)
{
    for(int i=1;i<n;++i)
    {
        if(v[i-1]<v[i])
        {
            continue;
        }
        return false;
    }
    return true;
}

int main()
{
    int n;
    cin>>n;

    vector<string> v(n);

    for(int i=0;i<n;++i)
    {
        cin>>v[i];
    }

    if(CheckDic(v,n)==true && CheckLength(v,n)==true)
    {
        cout<<"both"<<endl;
    }
    else if(CheckDic(v,n)==false && CheckLength(v,n)==true)
    {
        cout<<"lengths"<<endl;
    }
    else if(CheckDic(v,n)==true && CheckLength(v,n)==false)
    {
        cout<<"lexicographically"<<endl;
    }
    else
    {
        cout<<"none"<<endl;
    }

    return 0;
}

题目要求:

<1>.输入两个整数A,B
<2>.输出两个数的最小公倍数

解题思路:

<1>.如果A能整除B,那就输出A,如果B能整除A,那就输出B
<2>.求出两个数的最大公约数
<3>.然后,最小公倍数=两数乘积/最大公约数
<4>.这种常识我居然不知道,我是推了半天推出来的,一开始想的是大的那个数/最大公约数*小的那个数,通过70%

代码示例:

#include<iostream>

using namespace std;

int Func(int a,int b)
{
    //80 40--->40
    if(a%b==0)
    {
        return b;
    }
    //80 70 --->70 10-->10
    return Func(b,a%b);
}

int main()
{
    int A;
    int B;
    
    cin>>A>>B;

    int C=Func(A,B);

    if(A%B==0)
    {
        cout<<A<<endl;
    }
    else if(B%A==0)
    {
        cout<<B<<endl;
    }
    else
    {
        cout<<A*B/C<<endl;
    }

    return 0;
}

反思:

代码中有些地方根本就没用,要做到只写有用的代码…

正确代码示例:

#include<iostream>

using namespace std;

int Func(int A, int B)
{
	int C;
	while (C = A%B)
	{
		A = B;
		B = C;
	}
	return B;
}
int main()
{
	int A, B;

	while (cin >> A >> B)
	{


		cout << A*B / Func(A,B) << endl;
	}

	system("pause");
	return 0;
}

m*n的棋盘走法、另类的加法

题目要求:

<1>.输入两个数字n为横向的格子数,m为竖向的格子数
<2>.能往右和往下走,不能往左和往上走,从左上角走到右下角有多少种走法
<3>.输出正整数作为结果

解题思路:

<1>.使用vector创建一个二维数组,把第一行所有列置为1,把所有行第一列置为1
<2>.从vv[1][1]开始计算,vv[i][j]=vv[i-1][j]+vv[i][j-1];
<3>.返回最后的vv[m][n];

我当时绝对是脑子有病了,没用while(cin>>m>>n),导致0%通过…

代码示例:

#include<iostream>
#include<vector>

using namespace std;

int main()
{
    int m,n;

    while(cin>>m>>n)
    {
        vector<vector<int>> vv;

        vv.resize(m+1);

        for(auto& e:vv)
        {
            e.resize(n+1,0);
        }

        for(int i=0;i<=m;++i)
        {
            vv[i][0]=1;

            for(int j=0;j<=n;++j)
            {
                vv[0][j]=1;
            }
        }

        for(int i=1;i<=m;++i)
        {
            for(int j=1;j<=n;++j)
            {
                vv[i][j]=vv[i-1][j]+vv[i][j-1];
            }
        }

        cout<<vv[m][n]<<endl;
    }

    return 0;
}

题目要求:

<1>.不可以使用加法运算符和其他运算符,完成加法操作
<2>.输入两个数A,B
<3>.输出相加的结果

解题思路:

<1>.使用位运算,A作为进位,B作为结果
<2>.最后输出B

代码示例:

#include<iostream>

using namespace std;

int main()
{
    int A,B;

    while(cin>>A>>B)
    {
        while(A!=0)
        {
            int tmp=B;
            B=A^B;
            A=A&tmp;
            A<<=1;
        }
        return B;
    }

    return 0;
}

反思:

int fun(int a)
{
	a^=(1<<5)-1;
	return a;
}
fun(21)运行结果是(10)
当一个类的某个函数被说明为virtual,则在该类的所有派生类中的同原型函数_____?

A 只有 被重新说明时才识虚函数
B 只有被重新说明为virtual时才是虚函数
C 都不是虚函数
D 都是虚函数

他的回答: B (错误)
正确答案: D

目前还没弄到这…

class Test{
public:
	int a;
	int b;
	virtual void fun() {}
	Test(int temp1 = 0, int temp2 = 0)
	{
		a = temp1;
		b = temp2;
	}
	int getA()
	{
		return a;
	}
	int getB()
	{
		return b;
	}
};
int main()
{
	Test obj(5, 10);
	// Changing a and b
	int* pInt = (int*)&obj;
	*(pInt + 0) = 100;
	*(pInt + 1) = 200;
	cout << "a = " << obj.getA() << endl;
	cout << "b = " << obj.getB() << endl;
	return 0;
}

输出为 200 10
*(pInt+0)指向的是虚函数表指针
(pInt+1)和(pInt+2)分别指向a和b

<1>.两个数二进制位的异或运算相当于对应位相加,不考虑进位
<2>.二进制位的与运算相当于对应位相加之后的进位
<3>.两数相加=对应位相加的结果+进位的结果

正确代码示例:

class UnusualAdd 
{
public:
	int addAB(int A, int B)
	{
		int sum = 0;
		int C = 0;

		while (B != 0)
		{
			sum = A^B;
			C = (A&B) << 1;
			A = sum;
			B = C;
		}
		return sum;
	}
};

井字棋胜负检测、密码强度等级

题目要求:

<1>.给定一个井字棋的棋盘,1是玩家棋子,-1是对方棋子,0表示没棋子
<2>.一整行都是玩家棋子,或者一整列都是玩家棋子,或者两条对角线都是玩家棋子即为胜利

解题思路:

写的简洁点,就用个循环,不简洁就一条一条if判断

期待答案的高效算法,wotaicaile,我实在高效不起来…

代码示例:

#include<iostream>
#include <vector>

using namespace std;

class Board
{
public:
	bool checkWon(vector<vector<int> > board)
	{
		if (board[0][0] == 1 && board[0][1] == 1 && board[0][2] == 1)
		{
			return true;
		}
		if (board[1][0] == 1 && board[1][1] == 1 && board[1][2] == 1)
		{
			return true;
		}
		if (board[2][0] == 1 && board[2][1] == 1 && board[2][2] == 1)
		{
			return true;
		}
		if (board[0][0] == 1 && board[1][0] == 1 && board[2][0] == 1)
		{
			return true;
		}
		if (board[0][1] == 1 && board[1][1] == 1 && board[2][1] == 1)
		{
			return true;
		}
		if (board[0][2] == 1 && board[1][2] == 1 && board[2][2] == 1)
		{
			return true;
		}
		if (board[0][0] == 1 && board[1][1] == 1 && board[2][2] == 1)
		{
			return true;
		}
		if (board[2][2] == 1 && board[1][1] == 1 && board[0][0] == 1)
		{
			return true;
		}
		return false;
	}
};

题目要求:
<1>.输入一个字符串,根据要求算出得分,根据得分输出

	<2>.一、密码长度:5 分: 小于等于4 个字符,10 分: 5 到7 字符,25 分: 大于等于8 个字符  
	
		二、字母:0 分: 没有字母,10 分: 全都是小(大)写字母,20 分: 大小写混合字母  
		
		三、数字:0 分: 没有数字,10 分: 1 个数字,20 分: 大于1 个数字
		  
		四、符号:0 分: 没有符号,10 分: 1 个符号,25 分: 大于1 个符号 
		 
		五、奖励:2 分: 字母和数字,3 分: 字母、数字和符号,5 分: 大小写字母、数字和符号  
		
		最后的评分标准:>= 90: 非常安全,>= 80: 安全(Secure),>= 70: 非常强,>= 60: 强(Strong),
		>= 50: 一般(Average),>= 25: 弱(Weak),>= 0:  非常弱 
		 
	<3>.对应输出为:  VERY_WEAK,WEAK,AVERAGE,STRONG,VERY_STRONG,SECURE,VERY_SECURE

解题思路:

<1>.先判断长度
<2>.在判断数字个数
<3>.在判断大写字母,小写字母
<4>.最后的就是符号

代码示例:

#include<iostream>
#include <string>

using namespace std;

int GetPwdSecurityLevel(string password)
{
	int level = 0;

	//长度检测
	if (password.length() <= 4)
	{
		level += 5;
	}
	else if (password.length() >= 5 && password.length() <= 7)
	{
		level += 10;
	}
	else
	{
		level += 25;
	}

	//字母检测,符号检测,数字检测
	int AZflag = 0;
	int azflag = 0;
	int sysflag = 0;
	int count = 0;
	int syscount = 0;

	for (int i = 0; i < password.length(); ++i)
	{
		if (password[i] >= 'a'&&password[i] <= 'z') 
		{
			azflag = 1;
		}
		else if (password[i] >= 'A'&&password[i] <= 'Z')
		{
			AZflag = 1;
		}
		else if (password[i] >= '0'&&password[i] <= '9')
		{
			count++;
		}
		else
		{
			sysflag = 1;
			syscount++;
		}
	}

	//字母得分
	if (azflag == 1 && azflag == 1)
	{
		level += 20;
	}
	else if (azflag == 1 || AZflag == 1)
	{
		level += 10;
	}
	else
	{
		level += 0;
	}

	//数字得分
	if (count == 0)
	{
		level += 0;
	}
	else if (count == 1)
	{
		level += 10;
	}
	else
	{
		level += 20;
	}

	//符号得分
	if (syscount == 0)
	{
		level += 0;
	}
	else if (syscount == 1)
	{
		level += 10;
	}
	else
	{
		level += 25;
	}

	//奖励
	if ((AZflag == 1 || azflag == 1) && count > 0 && sysflag == 0)//字母,数字有,无符号
	{
		level += 2;
	}
	else if ((AZflag == 1 || azflag == 1) && count > 0 && syscount > 0)//字母符号数字都有
	{
		level += 3;
	}
	else if ((AZflag == 1 && azflag == 1) && count > 0 && syscount > 0)//大小写字母,数字,符号
	{
		level += 5;
	}
	else
	{
		level += 0;
	}

	return level;
}

int main()
{
	string pPasswordStr;

	while (getline(cin, pPasswordStr))
	{
		GetPwdSecurityLevel(pPasswordStr);

		if (GetPwdSecurityLevel(pPasswordStr) >= 90)
		{
			cout << "VERY_SECURE" << endl;
		}
		else if (GetPwdSecurityLevel(pPasswordStr) >= 80)
		{
			cout << "SECURE" << endl;
		}
		else if (GetPwdSecurityLevel(pPasswordStr) >= 70)
		{
			cout << "VERY_STRONG" << endl;
		}
		else if (GetPwdSecurityLevel(pPasswordStr) >= 60)
		{
			cout << "STRONG" << endl;
		}
		else if (GetPwdSecurityLevel(pPasswordStr) >= 50)
		{
			cout << "AVERAGE" << endl;
		}
		else if (GetPwdSecurityLevel(pPasswordStr) >= 25)
		{
			cout << "WEAK" << endl;
		}
		else if (GetPwdSecurityLevel(pPasswordStr) >= 0)
		{
			cout << "VERY_WEAK" << endl;
		}
	}

	system("pause");
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值