zoukankan      html  css  js  c++  java
  • noi-openjudge[4.7搜索]怀表问题

    为啥我觉得这是个DP….f[i][j][k][l]表示四种零件分别用了i,j,k,l个的方案数。然后发现这样不能保证表一定能接在表链首尾,也不知道状态之间如何转移,那么加一维变成f[i][j][k][l][S],S表示首尾的状态(4种),于是就可以预处理了。然后我们需要从给出的一共n个4种零件中选出k个。那么dfs暴力枚举方案。

    一开始DP求的状态是i,j,k,l四维都取到1-40,算了一些冗余状态,T了……后来限制四维之和小于等于40,A了……不过慢死…好像别人是直接搜的,加个记忆化?因为真正用到的状态数目不多所以会比较快?

    #include<cstdio>
    typedef long long ll;
    ll f[45][45][45][45][4];//4:首-尾字母 
    void dp(){//并不是所有状态都会被用到? 
        f[1][0][0][0][0]=f[0][1][0][0][1]=f[0][0][1][0][2]=f[0][0][0][1][3]=1;
        for(int i=0;i<=40;++i){
            for(int j=0;i+j<=40;++j){
                for(int k=0;i+j+k<=40;++k){
                    for(int l=0;i+j+k+l<=40;++l){
                        if(i+j+k+l==1)continue;
                        for(int s=0;s<4;++s){
                            if(i!=0&&(s&1)==0)f[i][j][k][l][s]+=f[i-1][j][k][l][s];
                            if(j!=0&&(s&1)==1)f[i][j][k][l][s]+=f[i][j-1][k][l][s^1];
                            if(k!=0&&(s&1)==0)f[i][j][k][l][s]+=f[i][j][k-1][l][s^1];
                            if(l!=0&&(s&1)==1)f[i][j][k][l][s]+=f[i][j][k][l-1][s];
                        }
                    } 
                } 
            } 
        }
    }
    int cnt[4];
    int sol[4];
    ll ans=0;int S;
    int n,k;
    void dfs(int x,int sum){
        if(x==4){
            if(sum==0)ans+=f[sol[0]][sol[1]][sol[2]][sol[3]][S];
            return;
        }
        for(int i=0;i<=cnt[x]&&i<=sum;++i){
            sol[x]=i;
            dfs(x+1,sum-i);
            sol[x]=0;
        }
        
    }
    int main(){
        dp();
        char buf[3];
        while(scanf("%d%d",&n,&k)!=EOF){
            scanf("%s",buf);
            S=0;
            if(buf[0]=='V')S+=1;
            if(buf[1]=='V')S+=2;
            cnt[0]=cnt[1]=cnt[2]=cnt[3]=0;
            for(int i=1;i<=n;++i){
                scanf("%s",buf);
                int tmp=0;
                if(buf[0]=='V')tmp+=2;
                if(buf[1]=='V')tmp+=1;
                cnt[tmp]++;
            }  
            ans=0;
            dfs(0,k);
    
            if(ans==0)printf("NO
    ");
            else printf("YES
    %lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    hdu 1042 N!
    hdu 1002 A + B Problem II
    c++大数模板
    hdu 1004 Let the Balloon Rise
    hdu 4027 Can you answer these queries?
    poj 2823 Sliding Window
    hdu 3074 Multiply game
    hdu 1394 Minimum Inversion Number
    hdu 5199 Gunner
    九度oj 1521 二叉树的镜像
  • 原文地址:https://www.cnblogs.com/liu-runda/p/6049540.html
Copyright © 2011-2022 走看看