hdu2894解题报告 DeBruijin

48 篇文章 0 订阅

DeBruijin

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 321    Accepted Submission(s): 205


Problem Description
旋转鼓的表面分成m块扇形,如图所示(m=8)。图中阴影区表示用导电材料制成,空白区用绝缘材料制成,终端a、b和c是3(k=3)处接地或不是接地分别用二进制信号0或1表示。因此,鼓的位置可用二进制信号表示。试问应如何选取这8个扇形的材料使每转过一个扇形都得到一个不同的二进制信号,即每转一周,能得到000到111的8个数。


那我们现在把旋转鼓的表面分成m块扇形,每一份记为0或1,使得任何相继的k个数的有序组(按同一方向)都不同,对固定的k,m最大可达到多少,并任意输出符合条件的一个这样的有序组。

 

Input
每个case输入一个数k (2<=k<=11),表示图中所示的abc这样的接地线的数量。
 

Output
每个case输出m所能达到的最大值 ,并且输出字典序最小的一个符合条件的有序组,中间用空格隔开。Case间没有空行。有序组输出的格式为:00010111(k=3,只输出一个周期(0001011100010111……),并且首尾刚好是相接的)。
 

Sample Input
  
  
3
 

Sample Output
  
  
8 00010111
 

Source
和上一题一样,其实,000到001,其实00是不变的,可以抽象成点,而000,001都是只有一个,可以抽象成边,那么这题就可以做出来了,以0——2^(n-1)-1为编号建立一棵树,共2^(n-1)个节点,如果在某个节点后面添加一个0或者1,再去掉最高位,得到下一个节点,两节点之间连一条有向边。图中每条边就表示了一个数,共有2^n个数,各不相同!题目要求字典序最小,则从2^(n-1-1节点开始,并且每个节点先连加0的边,后连加1的边,这样的话,就能保证最终的字典序最小。还是欧拉回路,都是一个模型,算法也就那个一个。只是这里,为什么,我取模了,提交OJ反而会快10几Ms,这一点,我不明白的!

#include <iostream>
#include<stdio.h>
#include<vector>
using namespace std;
struct tree{
      int v;
      int id;
      int to;
      int  flag;
};
int step;
vector<tree > p[35000];
bool re[35000];
int path[35000];
void dfs(int u)
{
      for(int i=0;i<p[u].size();i++)
      {
            if(!re[p[u][i].id])
            {
                  re[p[u][i].id]=true;
                  dfs(p[u][i].to);
                  path[step++]=p[u][i].flag;
            }
      }

}
int main()
{
      int i,k,n,tt;
      tree temp;
    while(~scanf("%d",&k))
    {

          n=1<<(k-1);
         // printf("%d n\n",n);
          for(i=0;i<=n;i++)
            p[i].clear();
          for(i=0;i<n;i++)
          {
             tt=((i<<1)-((i&(1<<(k-2)))<<1));
           // printf("%d tt\n",tt);
             tt=tt%n;

             temp.to=tt;
             temp.id=i<<1;
             temp.v=i;
             temp.flag=0;
             p[i].push_back(temp);
             re[temp.id]=false;
             tt+=1;
             //printf("%d tt\n",tt);如果是从反着建,就要从0开始DFS了这一点要注意
             tt=tt%n;

             temp.v=i;
             temp.to=tt;
             temp.id=i<<1|1;
             temp.flag=1;
             re[temp.id]=false;
             p[i].push_back(temp);

          }
          step=0;
          dfs(n-1);
          printf("%d ",n<<1);
          for(i=step-1;i>=0;i--)
          {
            printf("%d",path[i]);
          }
          printf("\n");

    }

    return 0;
}



  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值