Đề bài :
Cho chuỗi "((((1?2)?3)?4)?5)?6 = 36"
Thay thế dấu chấm hỏi ? bằng các toán tử '+', '-', '*', '/'
Sao cho biểu thức đúng
Output :
((((1*2)*3)/4)+5)*6
((((1*2)+3)/4)+5)*6
((((1*2)+3)-4)+5)*6
((((1/2)-3)+4)+5)*6
((((1+2)+3)/4)+5)*6
((((1-2)*3)+4)+5)*6
((((1-2)+3)+4)*5)+6
Em giải theo cách :
- Liệt kêu các trường hợp của biểu thức bằng giải thuật sinh chỉnh hợp lặp hiện thực theo giải thuật quay lui BackTracking (Hàm Try)
- Chuyển biểu thức dạng trung tố sang hậu tố (Hàm I2P)
- Tính toán biểu thức theo giải thuật người Ba lan (Hàm CalculateRPN)
Em gặp bài này vì có 1 người bạn hỏi. Không biết các bác có hướng nào làm khác cho bài toán này không.
#include <iostream>
#include <cstdint>
#include <string>
#include <stack>
#define SIZE 5 // Số dấu ?
using namespace std;
// # Khai báo prototype
int rnk(char ch); // Hàm tính độ ưu tiên toán tử
string I2P(string s); // Hàm chuyển biểu thức trung tố sang hậu tố
int CaculateRPN(string s);// Hàm tính toán theo giải thuật người ba lan
// Dữ liệu kiểm tra
string Ex = "((((1?2)?3)?4)?5)?6";
string Rs = "36";
// Mảng chứa các toán tử
string Op = "*/+-";
// Mảng chứa các cấu hình sinh chỉnh hợp lặp
char Se[SIZE];
// Hàm in cấu hình
void Find() {
// Tạo biểu thức trung tố
string IE(Ex); uint8_t index = 0;
for(int i = 0; i < IE.length(); ++i)
if(Ex[i] == '?') IE[i] = Se[index++];
// Chuyển biểu thức trung tố -> hậu tố
string PE = I2P(IE);
// Tính toán theo giải thuật người Ba lan
if(CaculateRPN(PE) == stoi(Rs)) cout << IE << endl;
}
// Giải thuật BackTracking
// Sinh chỉnh hợp lặp
void Try(int i) {
for(int j = 0; j < 4; ++j) {
Se[i] = Op[j];
if(i == SIZE - 1) Find();
else Try(i + 1);
}
}
// Kiểm tra hàm
int main()
{
Try(0);
return 0;
}
int rnk(char ch) {
switch(ch) {
case '*' : case '/' : return 2;
case '+' : case '-' : return 1;
}
return 0;
}
string I2P(string s) {
string result = "";
stack<char> stk;
for(auto ch : s) switch(ch) {
case '(' : stk.push(ch); break;
case ')' :
char temp;
do {
temp = stk.top(); stk.pop();
if(temp != '(') result += temp;
} while(temp != '('); break;
case '+' : case '-' :
case '*' : case '/' :
while(!stk.empty() && rnk(ch) <= rnk(stk.top()))
{result += stk.top(); stk.pop();}
stk.push(ch); break;
default : result += ch; break;
}
while(!stk.empty())
{result += stk.top();stk.pop();}
return result;
}
int CaculateRPN(string s) {
stack<int> stk;
int a, b;
for(char ch : s) switch(ch) {
case '+' :
b = stk.top(); stk.pop();
a = stk.top(); stk.pop();
stk.push(a + b); break;
case '-' :
b = stk.top(); stk.pop();
a = stk.top(); stk.pop();
stk.push(a - b); break;
case '*' :
b = stk.top(); stk.pop();
a = stk.top(); stk.pop();
stk.push(a * b); break;
case '/' :
b = stk.top(); stk.pop();
a = stk.top(); stk.pop();
stk.push(a / b); break;
default :
string str = "";
str += ch;
stk.push(stoi(str));
break;
}
return stk.top();
}
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?