zoukankan      html  css  js  c++  java
  • 星象仪

    星象仪
    (pla.pas/c/cpp)

    题目描述
    在寂寞的夜里,星象仪是非常浪漫的东西。但是,你作为一个精神稍微有点不太正常的Geek,

    把原本正常的星象仪改造得像电报发送器一样。当然,你这个的构造还要更加奇葩一点。具

    体来说,你的星象仪是一棵满二叉树,二叉树的节点都是有两个输入端和一个输出端的AND

    门或者OR 门。它们输入和输出的信号都是只是0 或者1。它们会接受子节点的输出信号,

    然后将这两个信号进行AND 运算或者OR 运算作为自己的输出。然后,根节点的输出信号

    就是整个星象仪的输出信号。叶节点的输入信号是由你来调整的,如果二叉树有K 层,那

    么你显然有2K 个输入信号可以调整。调整一次当然只能改变一个输入信号。如左图所示,

    这就是一台你改造过之后的星象仪。根据你的设定,在一开始所有的输入端的输入信号都是

    0。现在你希望用星象仪得到一串信号,为此,你需要不停地调整输

    入。假定你想要用左图中的星象仪得到输出信号000111,一种可行的方案是0001→0011→

    1100→1111→1010→0101,但是这样你要调整14 次输入信号。更加方便的方式是0000→

    0000→0000→0101→0101→0101,这样你总计只需要调整2次输入信号。由于调整输入信号

    是一件非常麻烦的事情,现在你希望知道对于一台给定的星象仪,如果想要得到一串给定的

    信号,至少需要调整多少次输入。

    输入格式

    输入文件包含多组测试数据。第一行有一个整数T,表示测试数据的组数。

    测试数据的第一行是一个正整数 N,表示输入信号的数目。保证N 是2 的整数次幂。

    第二行含有一个由 0 和1 组成的字符串S,表示你想要得到的信号。

    第三行包含 N – 1 个整数,按照层次遍历顺序给出满二叉树的每个节点。整数只会是0或者1。

       0 表示二叉树的这个位置是一个OR 门,1 表示是一个AND 门。

    对于每组测试数据,在单独的一行内输出结
    样例输入
    2
    4
    010101
    0 0 0
    4
    111111
    1 1 1
    样例输出
    5
    4

    数据范围与约定 

    对于30% 的数据,N≤16,S 的长度在100 之内。

    对于 100% 的数据,T≤100,N≤8192,S 的长度在 10000 之内。

    思路:首先,普及一下and,or   其实就是交集并集的关系

            当且仅当两个数都是1,and的值为1,

            两个数中存在1,or的值为1,

            看到二叉树,心中莫名高兴,不用谢邻接表了

            付题目中的图

    如果使1号点输出1,那么2,3号点都要为1,

    二号点为1,那么,4,5号点有一个为1,

    同理,6,7号点有一个为1,

    那么,从全0状态到输出1,只需要更改2个点

    然后,从输出1到输出0,更改的点数一定小于等于从全0状态到输出1更改的点数

    然后呢?

    树p

    对于一个全0状态的树,如果要输出1,那么,对于每一个节点,

    如果是and,则选择他的所有儿子都为1的方案数,

    如果是or,则选择它的儿子中为1的方案数的最小值

    (结果为第一次变换是使用)

    然后,对于一个输出1 的树的每一个节点,

    如果是and,则选择将其中一个节点变为0,

    如果是or,则将其原来选择变为1的节点变为0,

    (结果为以后的变换时使用)

    附代码:

    program ex02;
    var tree,a:array[0..100000] of longint;
        ss:ansistring;
        t,n,i:longint;
    procedure init;
    var i:longint;
    begin
      readln(n);
      readln(ss);
      for i:=1 to n-1 do
      begin
       read(tree[i]);
      end;
    end;
    function min(a,b:longint):longint;
    begin
      if a<b then exit(a);
      exit(b);
    end;
    function dfs2(root:longint):longint;   //第二次树p
    begin
      if root>=n then exit(1);
      if tree[root]=0 then
      begin
        if a[root]=a[root*2] then dfs2:=dfs2(root*2) else dfs2:=dfs2(root*2+1);
      end
      else
      if tree[root]=1 then
      begin
        dfs2:=min(dfs2(root*2),dfs2(root*2+1));
      end;
    end;
    
    function dfs1(root:longint):longint;  //第一次树p
    begin
      if root>=n then exit(1);
      if tree[root]=0 then
      begin
        dfs1:=min(dfs1(root*2+1),dfs1(root*2));
        a[root]:=dfs1;
      end
      else
      if tree[root]=1 then
      begin
        dfs1:=dfs1(root*2)+dfs1(root*2+1);
        a[root]:=dfs1;
      end;
    end;
    procedure doit;
    var i,k1,k2,ans:longint;
        flag:boolean;
    begin
      k1:=dfs1(1);
      k2:=dfs2(1);
      flag:=true; ans:=0;
      ss:='0'+ss;
      for i:=2 to length(ss) do   //计算方案数
      begin
        if ss[i]<>ss[i-1] then
        if (ss[i]='1') and (flag=true) then  //如果是第一变换
        begin
          flag:=false;
          ans:=ans+k1;
        end
        else                               //以后的变换
        begin
          ans:=ans+k2;
        end;
      end;
      writeln(ans);
    end;
    begin
      assign(input,'pla.in'); reset(input);
      assign(output,'pla.out'); rewrite(output);
      readln(t);
      for i:=1 to t do
      begin
        fillchar(a,sizeof(a),0);
        init;
        doit;
      end;
      close(input);
      close(output);
    end.
  • 相关阅读:
    dotnet 新项目格式与对应框架预定义的宏
    dotnet 线程静态字段
    dotnet 线程静态字段
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取系统信息
    dotnet 通过 WMI 获取系统信息
    PHP show_source() 函数
  • 原文地址:https://www.cnblogs.com/fengjunjie/p/6027995.html
Copyright © 2011-2022 走看看