您的位置:首页 > 其它

URAL-1101. Robot in the Field

2017-09-07 22:06 344 查看
1、知识点:动态规划

2、思路:此题最大的难点恐怕还是表达式处理,我用的是栈,代码比较长,但注释比较详细。

/*
*/

#include <stdio.h>
#include <string.h>
#include <string>
#include <stack>
using namespace std;
#define MAXN 100+10                     //N,M,K最大值
#define MAXEXPRELEN 250+10

struct Point{                           //点
int x;
int y;
int dir;                            //标记到当前点的方向
};
Point fork_point[MAXN];                 //分叉点
Point cur_poi;                          //当前点

struct Invert{                          //定义转换点
int a;
int b;
char c[5];
};
Invert inv[MAXN];                       //转换点
char sent[MAXEXPRELEN];                 //表达式
int reg_arr[26+5];                      //寄存器数组
int N,                                  //field
M,                                  //fork
K;                                  //register-invert-point

int get_val(const char *formu);         //计算表达式的值
int get_pri(string str);                //获取优先级
bool is_fork();                         //判断当前点是否分叉
void next_posi(int res, Point &poi);    //根据当前点计算下一个位置
bool is_out(Point poi);                 //检查新点是否出界
bool is_invert(int ®);               //检查当前点是否转换点,若是可得寄存器编号
int main()
{
memset(reg_arr, 0, sizeof(reg_arr));
gets(sent);
scanf("%d%d%d", &N, &M, &K);
for(int i=0; i<M; i++)
scanf("%d%d", &(fork_point[i].x), &(fork_point[i].y));

for(int j=0; j<K; j++)
scanf("%d%d%s", &(inv[j].a), &(inv[j].b), &(inv[j].c));

cur_poi.x = 1;
cur_poi.y = 0;
cur_poi.dir = 1;                        //(0,0)->(1,0):右
printf("%d %d\n", 0, 0);
printf("%d %d\n", 1, 0);
Point new_poi;
int inv_reg;                            //转换的寄存器编号
for(;;){
int res = -1;                       //默认直走
if(is_fork())                       //如果站在分叉点
res = get_val(sent);            //左,右?

if(is_invert(inv_reg))              //如果站在转换点
reg_arr[inv_reg] = 1 - reg_arr[inv_reg];

next_posi(res, new_poi);            //计算下一个点
bool ch = is_out(new_poi);          //检查新点是否出界
if(!ch){
printf("%d %d\n", new_poi.x, new_poi.y);
cur_poi.x = new_poi.x;
cur_poi.y = new_poi.y;
cur_poi.dir = new_poi.dir;
}
else
break;
}

return 0;
}

int get_val(const char *formu)
{
string expre = formu;
expre += "#";
int len = expre.length();
stack<string> sym;
stack<string> oper;
string str="";              //临时字符串
string top_str="";          //栈顶运算符
string top_oper="";         //栈顶操作数
int str_len=0;
sym.push("#");
for(int i=0; i<len; i++){
str += expre[i];
str_len++;
if(str == " "){                             //如果是空格
str = "";
str_len = 0;
continue;
}
if(isalpha(str[0])){
int j;
for(j=i+1; j<len; j++)
if(isalpha(expre[j])){
str += expre[j];
str_len++;
}
else
break;
i = j-1;                                //其它字符,i移至最后一个有效字符
}

if( str=="TRUE" || str=="FALSE" ||
(isalpha(str[0]) && str_len == 1))      //寄存器或真值
oper.push(str);
else{                                       //操作符 或 括号
if(get_pri(str) > get_pri(sym.top()) ||
(sym.top()=="("&&str!=")") || str=="NOT")//>栈顶优先级 或 栈顶是左括号 或 "NOT"(NOT是右结合)
sym.push(str);
else if(sym.top()=="(" && str==")")
sym.pop();
else{                                   //<栈顶优先级 或 右括号 或 "#"
while(sym.top()!="#" && get_pri(str)<=get_pri(sym.top()) && sym.top()!="("){
bool res = 0;                   //临时结果
string res_str = "";            //临时结果的字符串形式(TRUE,FALSE)
top_str = sym.top();            //弹出栈顶运算符
sym.pop();
top_oper = oper.top();          //弹出第一个操作数
oper.pop();
if(top_str == "NOT"){           //单操作数 (只有NOT一个)
if(top_oper == "TRUE")
res = 0;
else if(top_oper == "FALSE")
res = 1;
else
res = 1 - reg_arr[top_oper[0] - 'A'];
}
else{                           //双操作数
string sec_oper = oper.top();       //第二个操作数
oper.pop();
if(top_str == "AND"){               //AND
if(top_oper == "TRUE"){
if(sec_oper == "TRUE")
res = 1;
else if(sec_oper == "FALSE")
res = 0;
else
res = reg_arr[sec_oper[0] - 'A'];
}
else if(top_oper == "FALSE")
res = 0;
else{                           //第一个操作数是寄存器
if(!reg_arr[top_oper[0] - 'A'])
res = 0;
else{
if(sec_oper == "TRUE")
res = 1;
else if(sec_oper == "FALSE")
res = 0;
else
res = reg_arr[sec_oper[0] - 'A'];
}
}
}
else{                               //OR
if(top_oper == "TRUE")
res = 1;
else if(top_oper == "FALSE"){
if(sec_oper == "TRUE")
res = 1;
else if(sec_oper == "FALSE")
res = 0;
else
res = reg_arr[sec_oper[0] - 'A'];
}
else{                           //第一个操作数是寄存器
if(reg_arr[top_oper[0] - 'A'])
res = 1;
else{                       //第一个操作数为0
if(sec_oper == "TRUE")
res = 1;
else if(sec_oper == "FALSE")
res = 0;
else
res = reg_arr[sec_oper[0] - 'A'];
}
}
}
}

if(res == 1)
res_str = "TRUE";           //运算结果转换为字符串压栈
else
res_str = "FALSE";
oper.push(res_str);
if(str==")" && sym.top()=="("){ //遇到左括号退出循环
sym.pop();
break;
}
}

if(str != ")")
sym.push(str);                  //str入栈
}
}
str = "";
str_len = 0;
}
if(!oper.empty()){
string lst = oper.top();
if(lst == "TRUE")
return 1;
else if(lst == "FALSE")
return 0;
else
return reg_arr[lst[0] - 'A'];
}
else{
printf("oper stack is empty!");
return false;
}
}

int get_pri(string str)
{
int num = 6;
string prim[num] = {"#", ")", "OR", "AND", "NOT", "("};
for(int i=0; i<num; i++)
if(prim[i] == str)
return i;

return -1;
}

bool is_fork()                  //判断当前点是否分叉
{
for(int i=0; i<M; i++)
if(cur_poi.x == fork_point[i].x && cur_poi.y == fork_point[i].y)
return true;

return false;
}

void next_posi(int res, Point &poi)         //计算下一个位置
{
int dir = cur_poi.dir;                  //到当前点的方向
if(res == 1){                           //右拐
if(dir == 0){                       //原左
poi.x = cur_poi.x;
poi.y = cur_poi.y+1;
poi.dir = 2;
}
else if(dir == 1){                  //原右
poi.x = cur_poi.x;
poi.y = cur_poi.y-1;
poi.dir = 3;
}
else if(dir == 2){                  //原上
poi.x = cur_poi.x+1;
poi.y = cur_poi.y;
poi.dir = 1;
}
else{                               //原下
poi.x = cur_poi.x-1;
poi.y = cur_poi.y;
poi.dir = 0;
}
}
else if(res == 0){                      //左拐
if(dir == 0){
poi.x = cur_poi.x;
poi.y = cur_poi.y-1;
poi.dir= 3;
}
else if(dir == 1){
poi.x = cur_poi.x;
poi.y = cur_poi.y+1;
poi.dir = 2;
}
else if(dir == 2){
poi.x = cur_poi.x-1;
poi.y = cur_poi.y;
poi.dir = 0;
}
else{
poi.x = cur_poi.x+1;
poi.y = cur_poi.y;
poi.dir = 1;
}
}
else{                                   //直走
if(dir == 0){
poi.x = cur_poi.x-1;
poi.y = cur_poi.y;
}
else if(dir == 1){
poi.x = cur_poi.x+1;
poi.y = cur_poi.y;
}
else if(dir == 2){
poi.x = cur_poi.x;
poi.y = cur_poi.y+1;
}
else{
poi.x = cur_poi.x;
poi.y = cur_poi.y-1;
}
poi.dir = dir;
}
}

bool is_out(Point poi)                  //检查(x,y)是否出界
{
if(poi.x<-N || poi.x>N || poi.y<-N || poi.y>N)
return true;
else
return false;
}

bool is_invert(int ®)                //检查当前点是否转换点,若是,引用带回寄存器编号
{
for(int i=0; i<K; i++)
if(cur_poi.x == inv[i].a && cur_poi.y == inv[i].b){
reg = inv[i].c[0] - 'A';
return true;
}

return false;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: