码迷,mamicode.com
首页 > 其他好文 > 详细

【[CQOI2018]解锁屏幕】

时间:2019-01-01 21:04:19      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:clu   return   解锁   code   min   学生   check   max   stream   

状压这个东西好像没有什么能优化的高级东西,像什么斜率优化,单调队列在状压的优化上都很少见

而最常见的状压优化就是预处理优化了,

这道题就预处理一下所有点对之间连线上的点,之后压成状态就能做到\(O(2^n*n^2)\)

这道题的状态就非常简单了,就是一个小学生状压\(dp[i][S]\)状态为\(S\)时最后一个点是\(i\)的方案数

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define re register
#define lowbit(x) ((x)&(-x))
#define eps 1e-6
const int mod=100000007;
int n;
int dp[21][1048577];
int can[21][21];
inline int read()
{
    char c=getchar();
    int x=0,r=1;
    while(c<‘0‘||c>‘9‘) 
    {
        if(c==‘-‘) r=-1;
        c=getchar();
    }
    while(c>=‘0‘&&c<=‘9‘)
        x=(x<<3)+(x<<1)+c-48,c=getchar();
    return x*r;
}
inline int check(double x,double y)
{
    if(x+eps>y&&x-eps<y) return 1;
    return 0;
}
int X[21],Y[21];
inline int same(int a,int b,int c)
{
    if(X[c]<min(X[a],X[b])||X[c]>max(X[a],X[b])||Y[c]>max(Y[a],Y[b])||Y[c]<min(Y[a],Y[b])) return 0;
    if(X[a]==X[c]) return X[b]==X[c];
    if(X[b]==X[c]) return X[a]==X[c];
    return (Y[a]-Y[c])*(X[b]-X[c])==(Y[b]-Y[c])*(X[a]-X[c]);
}
inline int cnt(int x)
{
    int tot=0;
    while(x) tot++,x-=lowbit(x);
    return tot;
}
int main()
{
    n=read();
    for(re int i=1;i<=n;i++)
        X[i]=read(),Y[i]=read();
    int N=(1<<n)-1;
    for(re int i=1;i<=n;i++)
        for(re int j=i+1;j<=n;j++)
        {
            can[i][j]=can[j][i]=N;
            for(re int k=1;k<=n;k++)
                if(k!=i&&k!=j&&same(i,j,k)) can[i][j]^=(1<<(k-1)),can[j][i]^=(1<<(k-1));
        }
    for(re int i=1;i<=n;i++)
        dp[i][1<<(i-1)]++;
    for(re int i=1;i<N;i++)
        for(re int j=1;j<=n;j++)
            if(dp[j][i]&&(i&(1<<(j-1))))
            {
                for(re int k=1;k<=n;k++)
                if(!(i&(1<<(k-1)))&&((can[j][k]|i)==N)) 
                    dp[k][i|(1<<(k-1))]=(dp[k][i|(1<<(k-1))]+dp[j][i])%mod;
            }
    int ans=0;
    for(re int i=1;i<=N;i++)
    if(cnt(i)>=4) 
        for(re int j=1;j<=n;j++) 
            ans=(ans+dp[j][i])%mod;
    std::cout<<ans;
    return 0; 
}

【[CQOI2018]解锁屏幕】

标签:clu   return   解锁   code   min   学生   check   max   stream   

原文地址:https://www.cnblogs.com/asuldb/p/10205729.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!