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.
  • 相关阅读:
    switch语句(上)(转载)
    MSIL实用指南-生成if...else...语句
    Docker 部署Jira8.1.0
    K8S从入门到放弃系列-(13)Kubernetes集群mertics-server部署
    K8S踩坑篇-master节点作为node节点加入集群
    K8S从入门到放弃系列-(12)Kubernetes集群Coredns部署
    K8S从入门到放弃系列-(11)kubernetes集群网络Calico部署
    K8S从入门到放弃系列-(10)kubernetes集群之kube-proxy部署
    K8S从入门到放弃系列-(9)kubernetes集群之kubelet部署
    K8S从入门到放弃系列-(8)kube-apiserver 高可用配置
  • 原文地址:https://www.cnblogs.com/fengjunjie/p/6027995.html
Copyright © 2011-2022 走看看