• CQOI2018 解锁屏幕


    题目链接:戳我

    其实只有开了O2才能A.......

    就是我们看到n的范围这么小,就想到状压DP。然后我们设状态dp[i]表示状态为i的(二进制表示该点选或者不选),方案数有多少个。

    但是我们发现因为还要枚举转移下一个点,所以我们还要记录一下最后的那个点是什么。

    于是我们修改状态为(dp[i][j])表示当前状态为i,最后一个点的编号为j的,方案数有多少个。

    然后(O(2^n*n^2)).......吧

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define MAXN 21
    #define eps 1e-7
    #define mod 100000007
    using namespace std;
    int n,m,ans;
    int dp[1<<MAXN][MAXN];
    struct Node{int x,y;}node[MAXN];
    vector<int>mid[MAXN][MAXN];
    inline bool cmp(struct Node a,struct Node b)
    {
        if(a.x==b.x) return a.y<b.y;
        return a.x<b.x;
    }
    inline bool check(int a,int b,int c)
    {
        double k1,k2;
        if(node[a].x==node[b].x&&node[a].x==node[c].x) return true;
        else if(node[a].x==node[c].x||node[a].x==node[b].x) return false;
        k1=1.0*(node[a].y-node[b].y)/(node[a].x-node[b].x);
        k2=1.0*(node[a].y-node[c].y)/(node[a].x-node[c].x);
        if(fabs(k1-k2)<eps) return true;
        else return false;
    }
    inline bool more_than_4(int x)
    {
        int cur_ans=0;
        for(int i=0;i<n;i++)
            if(x&(1<<i))
                cur_ans++;
        return cur_ans>=4;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
                scanf("%d%d",&node[i].x,&node[i].y);
        sort(&node[1],&node[n+1],cmp);
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                for(int k=i+1;k<=j-1;k++)
                    if(check(i,j,k)==true)
                        mid[i][j].push_back(k);
        for(int i=1;i<=n;i++) dp[1<<(i-1)][i]=1;
        for(int i=1;i<(1<<n);i++)
        {
            for(int j=1;j<=n;j++)
            {
                if((i>>(j-1))&1) continue;
                int s=(i|(1<<(j-1)));
                for(int k=1;k<=n;k++)
                {
                    if(k==j) continue;
                    int x=min(j,k),y=max(j,k),flag=0;
                    for(int t=0;t<mid[x][y].size();t++)
                        if(!((i>>(mid[x][y][t]-1))&1)){flag=1;break;}
                    if(flag==1) continue;
                    dp[s][j]=(dp[s][j]+dp[i][k])%mod;
                }
            }
        }
        for(int i=1;i<(1<<n);i++)	
            if(more_than_4(i))
                for(int j=1;j<=n;j++)
                    ans=(ans+dp[i][j])%mod;
        printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    CMake 手册详解(十九)
    CMake 手册详解(二十三)
    CMake 手册详解(二十)
    xtrabackupex xbstream 流备份还原(转载)
    xtrabackup 安装与使用(转载)
    怎么样写好一篇技术博客
    python为什么需要符号表
    cmake的一些基本概念及源码结构
    让IT工作者过劳的13个坏习惯
    SHTML和HTML的区别
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10909237.html
Copyright © 2020-2023  润新知