zoukankan      html  css  js  c++  java
  • 状态压缩+升维dp——UCF 2016 I

    两种dp状态的设置法

    比较坑的一个地方:不论是哪种设置法,最后都要特判一下所有骨牌相同的情况,这种情况要把最后的结果/2

      因为此时每种骨牌排列,都可以将每块骨牌逆过来,还是合法的,基于我们设置的状态,这样就多统计了一倍,所以要/2

      只要有一块骨牌和其他不同,上述情况就不成立

    此外:当s[i]==t[i]时,我们只挑选一个计算贡献即可

    1.dp[S][i]:当前状态集合为S,末尾是i

    /*
    dp[01][1]=1
    dp[01][2]=1
    dp[10][1]=1
    dp[10][2]=1
    dp[11][1]=1
    dp[11][2]=1
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define mod 1000000007
    
    ll dp[1<<17][17],s[20],t[20],n;
    
    int main(){
        int T;cin>>T;
        while(T--){
            cin>>n;
            int flag=0;
            for(int i=0;i<n;i++){
                cin>>s[i]>>t[i];
                if(!(s[i]==s[0] && t[i]==t[0] || s[i]==t[0] && t[i]==s[0]))
                    flag=1;
            }
            if(!flag){
                ll ans=1;
                for(int i=1;i<=n;i++)
                    ans=ans*i%mod;
                cout<<ans<<'
    ';continue;
            }
            memset(dp,0,sizeof dp);
            
            dp[0][0]=1; 
            for(int S=0;S<(1<<n);S++){//当前状态是S 
                for(int i=0;i<n;i++)if(!(S>>i & 1)){
                    //把第i块放在最后的方案数
                    if(S==0){
                        dp[S|(1<<i)][s[i]]=(dp[S|(1<<i)][s[i]]+dp[S][0])%mod;
                        if(s[i]!=t[i])
                            dp[S|(1<<i)][t[i]]=(dp[S|(1<<i)][t[i]]+dp[S][0])%mod;
                    }
                    else  {
                        dp[S|(1<<i)][s[i]]=(dp[S|(1<<i)][s[i]]+dp[S][t[i]])%mod;
                        if(s[i]!=t[i])
                            dp[S|(1<<i)][t[i]]=(dp[S|(1<<i)][t[i]]+dp[S][s[i]])%mod;
                    }
                }
            }
            
            long long ans=0;
            for(int i=1;i<=6;i++)
                ans=(ans+dp[(1<<n)-1][i])%mod;
            cout<<ans<<'
    ';               
        }
    }

    2.dp[S][i][0|1] 状态集合S,最后一个是骨牌i,0|1正放,逆放

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define mod 1000000007
    
    ll dp[1<<17][17][2],s[20],t[20],n;
    
    int main(){
        int T;cin>>T;
        while(T--){
            cin>>n;
            int flag=0;
            for(int i=0;i<n;i++){
                cin>>s[i]>>t[i];
                if(!(s[i]==s[0] && t[i]==t[0] || s[i]==t[0] && t[i]==s[0]))
                    flag=1;
            }
            if(!flag){
                ll ans=1;
                for(int i=1;i<=n;i++)
                    ans=ans*i%mod;
                cout<<ans<<'
    ';continue;
            }
            
            memset(dp,0,sizeof dp);
            
            dp[0][0][0]=1; 
            for(int S=0;S<(1<<n);S++){//当前状态是S 
                if(S==0){
                    for(int i=0;i<n;i++){
                        dp[S|(1<<i)][i][0]=(dp[S|(1<<i)][i][0]+1)%mod;
                        dp[S|(1<<i)][i][1]=(dp[S|(1<<i)][i][1]+1)%mod;
                    }
                    continue;
                }
                for(int i=0;i<n;i++)if(S>>i & 1){//最后一块是i 
                    for(int j=0;j<n;j++)if(!(S>>j & 1)){
                        if(s[j]==t[i])
                            dp[S|(1<<j)][j][0]=(dp[S|(1<<j)][j][0]+dp[S][i][0])%mod;
                        if(s[j]==s[i] && s[i]!=t[i])
                            dp[S|(1<<j)][j][0]=(dp[S|(1<<j)][j][0]+dp[S][i][1])%mod;
                    
                        if(t[j]==t[i])
                            dp[S|(1<<j)][j][1]=(dp[S|(1<<j)][j][1]+dp[S][i][0])%mod;
                        if(t[j]==s[i] && s[i]!=t[i])
                            dp[S|(1<<j)][j][1]=(dp[S|(1<<j)][j][1]+dp[S][i][1])%mod;
                    }
                }
            }
            
            long long ans=0;
            for(int i=0;i<n;i++){
                ans=(ans+dp[(1<<n)-1][i][0])%mod;
                if(s[i]!=t[i])
                    ans=(ans+dp[(1<<n)-1][i][1])%mod;
            }
            cout<<ans<<'
    ';
        }
    }
  • 相关阅读:
    排序算法之希尔排序
    排序算法之插入排序(直接插入方式)
    排序算法之选择排序
    冒泡排序算法之优化
    排序算法之冒泡排序
    逻辑运算符:与,或,非,异或
    兔子个数问题(斐波那契数列)
    代理模式
    java.lang.ClassCastException: xut.bookshop.entity.User_$$_javassist_3 cannot be cast to javassist.util.proxy.Proxy
    org.xml.sax.SAXParseException; lineNumber: 14; columnNumber: 32; 元素类型为 "key" 的内容必须匹配 "(column)*"
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12602067.html
Copyright © 2011-2022 走看看