bzoj5299: [Cqoi2018]解锁屏幕

9.2s时间感人,没判好边界WA*2

这题看到n这么小,当然考虑一下状压

令f[i][zt]表示到达第i个点,zt就是取了和没取的状态咯

弄个li[i][j]表示假如i要->j,那么需要哪些点已经取了,这个根据题意就是斜率一样并且在两点之间

枚举状态,枚举出发和到达点,判断是否可行即可。

O(n^2*2^n),但是有很多到达不了的所以堪堪可过吧

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=100000007;

struct node
{
    int x,y;
}a[30];
int li[30][30];
LL f[21][1100000];
int main()
{
    freopen("data.in","r",stdin);
    freopen("1.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].x,&a[i].y);
    
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            int zz=0;
            for(int k=1;k<=n;k++)
                if(k!=i&&k!=j)
                {
                    if(
                    ((a[i].y-a[k].y)*(a[j].x-a[k].x)==(a[j].y-a[k].y)*(a[i].x-a[k].x))
                    &&
                    
                    (
                    ( (a[i].x<=a[k].x)&&(a[k].x<=a[j].x) && (a[i].y<=a[k].y)&&(a[k].y<=a[j].y) )
                    ||
                    ( (a[i].x>=a[k].x)&&(a[k].x>=a[j].x) && (a[i].y>=a[k].y)&&(a[k].y>=a[j].y) )
                    ||
                    ( (a[i].x>=a[k].x)&&(a[k].x>=a[j].x) && (a[i].y<=a[k].y)&&(a[k].y<=a[j].y) )
                    ||
                    ( (a[i].x<=a[k].x)&&(a[k].x<=a[j].x) && (a[i].y>=a[k].y)&&(a[k].y>=a[j].y) )
                    )
                    
                    )zz|=(1<<(k-1));
                }
            li[i][j]=li[j][i]=zz;
            li[i][j]|=(1<<(i-1));
            li[j][i]|=(1<<(j-1));
        }
    
    int u=(1<<n)-1;
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++)f[i][(1<<(i-1))]=1;
    for(int zt=1;zt<=u;zt++)
    {
        for(int i=1;i<=n;i++)
        {
            if((zt&(1<<(i-1)))>0&&f[i][zt]!=0)
            {                
                for(int j=1;j<=n;j++)
                {
                    if((zt&(1<<(j-1)))>0)continue;
                    if((zt&li[i][j])==li[i][j])
                        f[j][zt|(1<<(j-1))]=(f[j][zt|(1<<(j-1))]+f[i][zt])%mod;
                }
            }
        }
    }
    LL ans=0;
    for(int zt=1;zt<=u;zt++)
    {
        int o=0;
        for(int i=1;i<=n;i++)
            if((zt&(1<<(i-1)))>0)o++;
        if(o>=4)
        {
            for(int i=1;i<=n;i++)
                ans=(ans+f[i][zt])%mod;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AKCqhzdy/p/8939705.html
今日推荐