DAG优化
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
大家都学过了代码优化,其中有一个DAG优化,这次我们就练习这个操作。
Input
输入第一行为一个整数n(n < 100),表示该组输入的表达式的个数
之后n行为表达式,每个变量为一个字母,表达式仅包括二元运算 + - * /
例如:A=B+C
Output
通过构造DAG图,进行代码优化,只需要保留AB,删除无用变量,删除变量时,尽量保留最早出现的变量。
PS:保证AB的值不同
Sample Input
3
A=B+C
B=B+B
A=C+C
Sample Output
B=B+B
A=C+C
Hint
Source
基本的DAG图
这里只考虑了一种形式的表达式,即A=B op C, 且没有常数
#include<bits/stdc++.h>
using namespace std;
struct node
{
char flag;//都是字符型
int left=-1, right=-1;
vector<char> add;
}ans[101];
int m=0;
int find_add(int j, char c)
{
for(int i=0; i<ans[j].add.size(); i++)
{
if(c == ans[j].add[i])
{
return 1;
}
}
return 0;
}
int add_ans(char c)
{
//存在则返回ID
for(int j=0; j<m; j++)
{
if(c == ans[j].flag || find_add(j, c))
{
return j;
}
}
//不存在则新建结点,然后返回ID
ans[m].flag = c;
return m++;//***
}
void add_operator(char op, int l, int r, char add)
{
//已存在则添加到附加标记add后
for(int j=0; j<m; j++)
{
if(ans[j].flag==op && ans[j].left==l && ans[j].right==r)
{
ans[j].add.push_back(add);//***
return;
}
}
//不存在则新建结点
ans[m].flag = op;
ans[m].left = l;
ans[m].right = r;
ans[m].add.push_back(add);
m++;
return;
}
char s[11];
char map1[110][10];
int flag[110];
void dfs(int x)
{
if(ans[x].left != -1)//排除掉初始值A0,B0
{
flag[x]=1;
dfs(ans[x].left);
dfs(ans[x].right);
}
}
int main()
{
int n, j;
scanf("%d", &n);
for(int i=0; i<n; i++)
{
scanf("%s", s);//每次读一个字符数组
int l = add_ans(s[2]);
int r = add_ans(s[4]);
add_operator(s[3], l, r, s[0]);
}
// for(i=0; i<n; i++)
// {
// cin>>a[i];
// }
// for(i=0; i<n; i++)
// {
// if(judge(a[i][2])==-1)//y
// {
// ans[m].flag = a[i][2];//新建
// m++;
// }
// if(judge(a[i][4])==-1)//z
// {
// ans[m].flag = a[i][4];//新建
// m++;
// }
// int y, z;
// char op = a[i][3];
// y = judge(a[i][2]);
// z = judge(a[i][4]);
// int x = judge_yzop(y, z, op);
// if(x==-1)//不存在该结点,创建一个新的
// {
// ans[m].flag = a[i][3];
// ans[m].left = y;
// ans[m].right = z;
// delete_else(a[i][0]);
// ans[m].add.push_back(a[i][0]);
// m++;
// }
// else
// {
// delete_else(a[i][0]);
// ans[m].add.push_back(a[i][0]);
// }
//
// }
//输出基本DAG
for(j=0; j<m; j++)
{
printf("%d %c %d %d ", j, ans[j].flag, ans[j].left, ans[j].right);
for(int t=0; t<ans[j].add.size(); t++)//如果add不存在,则不会输出
{
printf("%c", ans[j].add[t]);
}
printf("\n");
}
for(j=0; j<m; j++)//再次转化为题例形式
{
if(ans[j].left != -1)
{
map1[j][0] = ans[j].add[0];
map1[j][1] = '=';
struct node ll = ans[ans[j].left];//左孩子
struct node rr = ans[ans[j].right];//右孩子
//只有初始的A0或B0没有附加标记add,有附加标记的就用附加标记
map1[j][2] = ll.add.size() > 0 ? ll.add[0] : ll.flag;
map1[j][3] = ans[j].flag;
map1[j][4] = rr.add.size() > 0 ? rr.add[0] : rr.flag;
map1[j][5] = 0;//没什么用
}
}
//后面遇到的第一个A或B,故无需删除之前的重复的
for(j=m-1; j>=0; j--)//从后面开始
{
if(map1[j][0] == 'A')
{
dfs(j);
break;//?
}
}
for(j=m-1; j>=0; j--)
{
if(map1[j][0] == 'B')
{
dfs(j);
break;//?
}
}
for(j=0; j<m; j++)
{
if(flag[j])
{
puts(map1[j]);
}
}
return 0;
}