zoukankan      html  css  js  c++  java
  • 机房测试:decoration(树+状压)

    题目:

     

     分析:

    这道题的难点在于:

    每一次转移的时候,要记录很多被翻转的点,还要确定他们下一次的fa是谁。

    所以转换一下思路:从终止状态转移到0状态(初始状态),倒着来。

    假设现在到了倒数第 i 秒,那么从第i~ans的时间内翻转了一个灯他是一直要向上跳并影响其他灯的,跳的时间为i,所以可以预处理一下:fa[i][j]表示i灯在跳j步后能变化到的状态

    每一次转移的时候,只需要枚举灯,异或上fa数组即可快速知道倒数第i+1秒的状态。

    某一次更新到了初始状态0,就直接输出现在是倒数第几秒即可。

    因为还要记录时间,所以dp要开两维。

    注意:如果一个点已经传递到了根节点,那么状态就不会变了!!

    #include<bits/stdc++.h>
    using namespace std;
    #define N 18
    #define ri register int
    int ff[N],fa[N][N],dp[N][1<<N],n,goal=0,x;
    int main()
    {
        freopen("decoration.in","r",stdin);
        freopen("decoration.out","w",stdout);
        scanf("%d",&n);
        ff[1]=0;
        for(ri i=2;i<=n;++i) scanf("%d",&x),ff[i]=x;
        for(ri i=1;i<=n;++i) scanf("%d",&x),goal<<=1,goal+=x;
        for(ri i=1;i<=n;++i){
            fa[i][0]=(1<<(n-i)); 
            int pre=ff[i];
            for(ri j=1;j<=n;++j){
                if(pre) fa[i][j]=fa[i][j-1]^(1<<(n-pre));//如果说已经到达根节点1了,就不用再跳了 
                else fa[i][j]=fa[i][j-1];
                pre=ff[pre];
            }
        }
        dp[0][goal]=1;
        for(ri t=0;t<=n;++t){
            if(dp[t][0]) { printf("%d
    ",t); return 0; }
            for(ri j=0;j<(1<<n);++j)
            if(dp[t][j]){
                dp[t+1][j]=1;
                for(ri k=1;k<=n;++k)
                dp[t+1][j^(fa[k][t])]=1;
            }
        }
        return 0;
    }
    /*
    7
    1 1 2 2 3 3
    0 1 1 1 0 0 1
    3
    
    7
    1 1 2 2 3 3
    1 1 1 1 0 0 1
    3
    
    8
    1 1 2 4 2 4 6
    0 0 1 0 1 1 0 1
    
    
    3 
    1 1
    0 1 1
    */
    View Code
  • 相关阅读:
    Vue之仿百度搜索框
    Vue之交互
    Vue之键盘事件
    Vue之事件冒泡
    Vue之阻止默认行为
    sql注入常用注释符总结
    什么是Git
    Github部署博客
    php笔记
    JavaScript(更新中)
  • 原文地址:https://www.cnblogs.com/mowanying/p/11794052.html
Copyright © 2011-2022 走看看