[360 가을채용 필기시험] 프로그래밍 문제 2: 웹을 수정하다 (C++의 AC 솔루션)

주제

먼저 예를 살펴보겠습니다.

6
16=1+2*3
7*8*9=54
1+1=1+22
4*6=22+2
15+7=1+2
11+1=1+5

n은 n행의 데이터를 입력한다는 의미이며, 아래의 각 행의 데이터는 방정식을 나타냅니다. 방정식의 양쪽이 모두 참이 되도록 방정식 에 숫자를 추가하는 것이 가능하면 Yes를 출력하고, 그렇지 않으면 No를 출력합니다. 방정식이 본질적으로 동일하면 Yes도 출력됩니다.

유일한 기호는 +, * 및 =입니다. 모두 양의 정수입니다.

분할 또는 계산이 올바른지 테스트하려면 다음 예를 사용하면 됩니다.

1
16=1+2*3

아이디어

약간 더 복잡한 시뮬레이션입니다.

계산을 수행하려면 방정식(문자열)을 숫자와 문자로 분할해야 합니다. 계산 과정은 스택을 사용하여 구현된 역 폴란드식 표현 과 유사합니다. 숫자를 더하면 방정식이 참이 되는지 여부에 대해 열거 할 수 있습니다 .

이 질문은 C++에서 해결되었습니다. ( 이런 종류의 데이터 입력은 C++에서 더 편리하게 느껴집니다. JS를 비동기식으로 사용해야 한다면?? 360의 프로그래밍 질문에는 입력용 템플릿이 없고 ACM 모드만 있습니다. )

문자열을 입력하고 숫자와 문자의 기능을 얻습니다. 중간은 cntNum、cntCh총 분할 수를 기록하는 데 사용되는 포인터입니다.

void stringTo(string a){
    
    
    int temp=0;
    for(int i=0;a[i];i++){
    
    
        if(a[i]>='0'&&a[i]<='9'){
    
    
            temp*=10;
            temp+=a[i]-'0';
        }else{
    
    
            ch[cntCh]=a[i];
            cntCh++;
            num[cntNum]=temp;
            cntNum++;temp=0;
        }
    }
    num[cntNum]=temp;
    cntNum++;temp=0;
}

등호 =의 왼쪽과 오른쪽에 있는 숫자를 계산하려면 반대 폴란드 표현을 사용하면 됩니다 .

여기서 왼쪽과 오른쪽 매개변수는 [left,right]배열의 답 계산을 나타냅니다. 이런 방식으로 등호의 왼쪽과 등호의 오른쪽을 각각 계산하려면 매개변수만 변경하면 됩니다.

숫자의 개수는 기호의 개수보다 1이 더 많기 때문에 첫 번째 숫자가 먼저 스택에 푸시될 수 있습니다.

//计算左右两边的大小 
//左 1,indexx
//右 indexx+1,end 
int cal(int left,int right){
    
    
	if(left==right) return num[left];
	
	stack<int>numm;stack<char>chh;
	numm.push(num[left]);
//	数字 
	for(int i=left+1;i<=right;i++){
    
    
		//对应的操作符是i-1的下标 
		char op=ch[i-1];
		//优先级高 
		if(op=='*'){
    
    
			int qian=numm.top();numm.pop();
			int hou=num[i];
			int temp=qian*hou;
			numm.push(temp);
		}
		else{
    
    
			numm.push(num[i]);
			chh.push(ch[i-1]);
		}
	}
	
//	计算加减
	
	while(chh.size()){
    
    
		char op=chh.top();chh.pop();
		int hou=numm.top();numm.pop();
		int qian=numm.top();numm.pop();
		int temp=qian+hou;
		numm.push(temp);
	} 
	return numm.top();
}

열거형은 문자열의 각 위치에 숫자를 삽입하고 다음을 계산합니다.

for(int i=0;a[i];i++){
    
    
	c.clear();
	b+=a[i];
	c+=b;
	for(int j=0;j<=9;j++){
    
    
		c+=char('0'+j);
		c+=a.substr(i+1);
		if(solve(c)) {
    
    
			flag=1;break;
		}
		c.clear();c+=b;
	}
	if(flag) break;
}

전체 과정: 문자열을 숫자와 기호로 변환, 계산. 이 프로세스는 다음과 같이 캡슐화될 수 있습니다.

bool solve(string a){
    
    
	clearr();
	stringTo(a);
	findEqual();
	l=cal(0,indexx);
	r=cal(indexx+1,cntNum-1);
	if(l==r) return true;
	else return false;
}

전체 코드(AC)

#include<bits/stdc++.h>
using namespace std;
int t;string a;
int num[5000];
char ch[5000];
int cntNum=0,cntCh=0;
int indexx;//=的下标 
int l,r;
void clearr(){
    
    
	cntNum=0,cntCh=0;
}
void stringTo(string a){
    
    
    int temp=0;
    for(int i=0;a[i];i++){
    
    
        if(a[i]>='0'&&a[i]<='9'){
    
    
            temp*=10;
            temp+=a[i]-'0';
        }else{
    
    
            ch[cntCh]=a[i];
            cntCh++;
            num[cntNum]=temp;
            cntNum++;temp=0;
        }
    }
    num[cntNum]=temp;
    cntNum++;temp=0;
}
//找到=的下标index 对应num的下标,index及其之前的都是=号左边的 
void findEqual(){
    
    
	for(int i=0;i<cntCh;i++){
    
    
		if(ch[i]=='='){
    
    
			indexx=i;break;
		}
	} 
}
//计算左右两边的大小 
//左 1,indexx
//右 indexx+1,end 
int cal(int left,int right){
    
    
	if(left==right) return num[left];
	
	stack<int>numm;stack<char>chh;
	numm.push(num[left]);
//	数字 
	for(int i=left+1;i<=right;i++){
    
    
		//对应的操作符是i-1的下标 
		char op=ch[i-1];
		//优先级高 
		if(op=='*'){
    
    
			int qian=numm.top();numm.pop();
			int hou=num[i];
			int temp=qian*hou;
			numm.push(temp);
		}
		else{
    
    
			numm.push(num[i]);
			chh.push(ch[i-1]);
		}
	}
	
//	计算加减
	
	while(chh.size()){
    
    
		char op=chh.top();chh.pop();
		int hou=numm.top();numm.pop();
		int qian=numm.top();numm.pop();
		int temp=qian+hou;
		numm.push(temp);
	} 
	return numm.top();
}

bool solve(string a){
    
    
	clearr();
	stringTo(a);
	findEqual();
	l=cal(0,indexx);
	r=cal(indexx+1,cntNum-1);
	if(l==r) return true;
	else return false;
}

int main(){
    
    
    cin>>t;
    while(t--){
    
    
    	clearr();l=0,r=0;
        cin>>a;
        stringTo(a);
        
//        找= index
		findEqual();
		l=cal(0,indexx);
		r=cal(indexx+1,cntNum-1);
		
		if(l==r) {
    
    
			cout<<"Yes"<<endl;continue;
		}
		
		string b,c;int flag=0;
		//在最前面加
		for(int i=0;i<=9;i++){
    
    
			c.clear();
			c+=char('0'+i);
			c+=a;
			if(solve(c)) {
    
    
				flag=1;break;
			}
		}
		if(flag) {
    
    
			cout<<"Yes"<<endl;continue;
		}
		
		b.clear();c.clear();
		 
		for(int i=0;a[i];i++){
    
    
			c.clear();
			b+=a[i];
			c+=b;
			for(int j=0;j<=9;j++){
    
    
				c+=char('0'+j);
				c+=a.substr(i+1);
				if(solve(c)) {
    
    
					flag=1;break;
				}
				c.clear();c+=b;
			}
			if(flag) break;
		}
		if(flag) {
    
    
			cout<<"Yes"<<endl;continue;
		}
		else cout<<"No"<<endl;    
    }
    return 0;
}

중요하지 않은 경험

문자열 계산 + 역 폴란드어 표현 + 열거 등 많은 요소가 포함된 매우 일반적인 시뮬레이션 질문입니다. 작성하는데 70분 넘게 걸렸네요!
입력 데이터 범위가 크지 않아 열거가 가능합니다. 더 좋은 글쓰기 방법이 있는지는 모르겠습니다.
코드가 난잡하게 작성되어 있고 능률적이지 않아서 시간나면 다시 작성하겠습니다.

추가로 저는 프론트엔드입니다! 하지만 프로그래밍 질문에서 비동기 데이터 입력을 위한 템플릿을 제공하지 않는 것을 보고 어안이 벙벙했습니다. . 이를 수행하는 방법. . 나는 C++로 질문을 작성했던 기억을 억지로 집어들어야 했다. 그렇지 않았다면 그것을 보냈을 것이다.

Supongo que te gusta

Origin blog.csdn.net/karshey/article/details/133216144
Recomendado
Clasificación