DAG优化

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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值