• Loj-SGU 223-国王


    题目

    题目链接

    测试得分:  100

    主要算法 :  状压DP(二进制优化)

    题干:

       状压DP板子

    分析

      1.对于国王这道题,有点类似于八皇后问题,但是这个点限制条件少一些,简单地说就是一次筛选的点较少,所以会导致搜索的超时

      2.那可不可以用多维DP呢?,对于每一行,我们知道它只于前一行与自身有关,满足了DP的无后效性原则,对于答案,是前面答案的汇总,通俗的讲就是满足最优子结构原理,所以yongDP

      3.但是对于DP状态转移所需要的值太多了,有前一行的状态与这一行的状态还有应该选取的国王数目

      4.对于状态记录繁琐,但是对于状态只有01两种选择,放与不放,所以可以将01串看作二进制数,则每一个状态对应一个唯一的十进制数,这就是这一题的核心思想状压

      5.好了上代码了

      代码

    #include<stdio.h>
    #include<stdlib.h>
    #define LL long long
    #define FORa(i,s,e) for(LL i=s;i<=e;i++)
    #define FORs(i,s,e) for(LL i=s;i>=e;i--)
    
    using namespace std;
    
    const LL N=10,SUM=1024,TRUES=144;/*每行骑士分布合法状态并没有这么多,我计算了一下最多也只有144个合法的状态 
    但是多开一点没有关系哈,新手嘛,但手贱的我还是改了 
    */
    LL n,k;
    LL sum,ans,num[TRUES+1],s[TRUES+1];
    LL f[N+1][TRUES+1][N*N+1];
    /*
    f[i][j][k]代表的是前i行并且第i行的状态是j&&安排的骑士个数是k时的合法方案
    j原本是一维的有n个元素的数组,代表的是第i行的状态,但是对于状态只有01两种选择,放与不放
    所以可以将01串看作二进制数,则每一个状态对应一个唯一的十进制数,这就是这一题的核心思想状压 
    */
    void Pre()
    {
        LL cnt;
        for(LL i=0,in=1<<n;i<in;i++)//枚举所有状态,筛选出合法状态 
        {
            if(i&(i<<1)) continue;//如果有两个1连在一起的话,直接过滤掉 
            cnt=0;
            for(LL j=0;j<n;j++)//累加这个状态中1出现的次数,这就是这个状态放置的骑士个数 
                if(i&(1<<j))
                    cnt++;
            s[++sum]=i,num[sum]=cnt;//存储 
        }
        
    }
    void Solve()
    {
        f[0][1][0]=1;//代表的是第0行不放时有1种选择,为什么第二个下标是1呢,因为s[1]为一个长度为n的只包含0的字符串 
        FORa(i,1,n)
            FORa(now,1,sum)//枚举现在这行的状态 
                FORa(pre,1,sum)//因为现在这行的状态至于上一行有关(最优子结构原理与无后效性原则),枚举上一行的状态 
                    if(!(s[now]&s[pre]))//如果上下两行之间没有列号为x的都是1的情况,继续 
                        FORa(tot,num[now],k)
                            if((!(s[now]&(s[pre]<<1)))&&(!(s[now]&(s[pre]>>1))))//判断对角线是否满足要求 
                                f[i][now][tot]+=f[i-1][pre][tot-num[now]];
        FORa(i,1,sum) ans+=f[n][i][k];//累加答案 
        printf("%lld",ans);
    }
    int main()
    {
        scanf("%lld%lld",&n,&k);
        Pre(),Solve();
        return 0;
    }

    总结:

      1.DP状态的确定

  • 相关阅读:
    python中range函数与列表中删除元素
    python碎片记录(一)
    Coursera在线学习---第八节.K-means聚类算法与主成分分析(PCA)
    Coursera在线学习---第七节.支持向量机(SVM)
    Coursera在线学习---第六节.构建机器学习系统
    Coursera在线学习---第五节.Logistic Regression
    梯度下降法与迭代结束条件
    利用并查集求最大生成树和最小生成树(nlogn)
    字符串二分查找
    map容器
  • 原文地址:https://www.cnblogs.com/SeanOcean/p/11354466.html
Copyright © 2020-2023  润新知