• P4460 [CQOI2018]解锁屏幕


    算是我比较擅长的类型,自己想想就会了。普通小状压,状态傻子都能想出来。一开始裸的枚举T了,30.后来与处理之后跑的飞起,就是不对,还是30分。后来看讨论版。。。mod竟然是1e8+7!!!这不有毒吗。。。

    题干:

    题目背景
    
    使用过Android 手机的同学一定对手势解锁屏幕不陌生。Android 的解锁屏幕由3X3 个点组成,手指在屏幕上画一条线,将其中一些点连接起来,即可构成一个解锁图案。如下面三个例子所示:
    
    题目描述
    
    画线时还需要遵循一些规则:
    
        连接的点数不能少于4 个。也就是说只连接两个点或者三个点会提示错误。
    
        两个点之间的连线不能弯曲。
    
        每个点只能“使用”一次,不可重复。这里的“使用”是指手指划过一个点,该点变绿。
    
        两个点之间的连线不能“跨过”另一个点,除非那个点之前已经被“使用”过了。
    
    对于最后一条规则,参见下图的解释。左边两幅图违反了该规则; 而右边两幅图(分别为2->4-1-3-6 和6->5-4->1->9-2) 则没有违反规则,因为在“跨过”点时,点已经被“使用”过了。
    
    现在工程师希望改进解锁屏幕,增减点的数目,并移动点的位置,不再是一个九宫格形状,但保持上述画线的规则不变。请计算新的解锁屏幕上,一共有多少满足规则的画线方案。
    输入输出格式
    输入格式:
    
    输入文件第一行,为一个整数n,表示点的数目。
    
    接下来n 行,每行两个空格分开的整数xix_ixi​ 和yiy_iyi​,表示每个点的坐标。
    
    输出格式:
    
    输出文件共一行,为题目所求方案数除以100000007 的余数。

    30

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(register int i = a;i <= n;++i)
    #define lv(i,a,n) for(register int i = a;i >= n;--i)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int mod = 1e9 + 7;
    const int N = 21;
    int dp[1 << N][N];
    int x[N],y[N],n,ans;
    /*void dfs(int now,int u,int len)//zhuangtai.xianzaidedian,changdu
    {
        if(dp[now][u]) return dp[now][u];
        for(int i = 1;i <= n;i++)
        {
            if(now & (1 << (i - 1)) == 0)
            {
                int ok = 0;
                duke(j,1,n)
                {
                    if(now & (1 << (i - 1)) == 0)
                    {
                        if(check(u,j,i) == false)
                        {
                            ok = 1;
                            break;
                        }
                    }
                }
                if(ok == 0)
                {
                    dfs(now | (1 << (i - 1)),i,len + 1);
                    dp[now][u] += dp[now | (1 << (i - 1))]
                }
            }
        }
    }*/
    bool check(int a,int b,int c)
    {
        /*if(a == 1 && c == 3 && b == 2)
        printf("%d %d %d
    ",a,b,c);*/
        if((y[b] - y[a]) * (x[c] - x[b]) != (y[c] - y[b]) * (x[b] - x[a]))
        return true;
        if(x[a] > x[b] && x[c] > x[b])
        return true;
        if(x[a] < x[b] && x[c] < x[b])
        return true;
        if(y[a] > y[b] && y[c] > y[b])
        return true;
        if(y[a] < y[b] && y[c] < y[b])
        return true;
        return false; 
    }
    void p(int now)
    {
        duke(i,1,n)
        {
            if((now & (1 << (i - 1))) != 0)
            printf("1");
            else
            printf("0");
        }
    }
    int main()
    {
        read(n);
        duke(i,1,n)
        read(x[i]),read(y[i]);
        duke(i,0,n - 1)
        {
            dp[1 << i][i + 1] = 1;
        }
        for(int now = 1;now <= (1 << n) - 1;now++)
        {
            duke(i,1,n)
            {
                if((now & (1 << (i - 1))) != 0)
                {
                    duke(j,1,n)
                    {
                        if((now & (1 << (j - 1))) != 0 && i != j)
                        {
                            int ok = 0;
                            duke(k,1,n)
                            {
                                if((now & (1 << (k - 1))) == 0)
                                    if(check(i,k,j) == false)
                                    {
                                        ok = 1;//cout<<i<<" "<<j<<" "<<k<<endl;
                                        break;
                                    }
                            }
                            if(ok == 0)
                            {
                                dp[now][i] += dp[now - (1 << (i - 1))][j];
    //                            p(now),printf(" ");cout<<i<<" "<<j;printf(" ");p(now - (1 << (i - 1)));
    //                            puts("");
                                dp[now][i] %= mod;
                            }
                        }
                    }
                }
            }
            int tot = 0;
            duke(i,0,n - 1)
            {
                if((now & (1 << i)) != 0)
                tot++;
            }
            if(tot >= 4)
            {
                duke(i,1,n)
                {
                    if((now & (1 << (i - 1))) != 0)
                    ans += dp[now][i],ans %= mod;
                }
            }
        }
    //    ans += 1;
    //    ans /= 2;
        /*duke(i,0,(1 << n) - 1)
        {
            duke(j,1,n)
            if((i & (1 << (j - 1))) != 0)
            p(i),printf(" "),cout<<dp[i][j]<<endl;
        }*/
        printf("%d
    ",ans);
        return 0;
    }

    AC代码:

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(register int i = a;i <= n;++i)
    #define lv(i,a,n) for(register int i = a;i >= n;--i)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int mod = 1e8 + 7;
    const int N = 21;
    int dp[1 << N][N];
    int x[N],y[N],n,ans;
    bool check(int a,int b,int c)
    {
        /*if(a == 1 && c == 3 && b == 2)
        printf("%d %d %d
    ",a,b,c);*/
        if((y[b] - y[a]) * (x[c] - x[b]) != (y[c] - y[b]) * (x[b] - x[a]))
        return true;
        if(x[a] > x[b] && x[c] > x[b])
        return true;
        if(x[a] < x[b] && x[c] < x[b])
        return true;
        if(y[a] > y[b] && y[c] > y[b])
        return true;
        if(y[a] < y[b] && y[c] < y[b])
        return true;
        return false; 
    }
    void p(int now)
    {
        duke(i,1,n)
        {
            if((now & (1 << (i - 1))) != 0)
            printf("1");
            else
            printf("0");
        }
    }
    vector <int> mp[N][N];
    void init(int x,int y)
    {
        for(int i = 1;i <= n;i++)
        {
            if(check(x,i,y) == false)
            {
                mp[x][y].push_back(i);
            }
        }
    }
    int main()
    {
        read(n);
        duke(i,1,n)
        read(x[i]),read(y[i]);
        duke(i,0,n - 1)
        {
            dp[1 << i][i + 1] = 1;
        }
        duke(i,1,n)
        duke(j,1,n)
        init(i,j);
        for(int now = 1;now <= (1 << n) - 1;now++)
        {
            duke(i,1,n)
            {
                if((now & (1 << (i - 1))) != 0)
                {
                    duke(j,1,n)
                    {
                        if((now & (1 << (j - 1))) != 0 && i != j)
                        {
                            int ok = 0;
                            duke(f,0,(int)mp[i][j].size() - 1)
                            {
                                int k = mp[i][j][f];
                                if((now & (1 << (k - 1))) == 0)
                                    {
                                        ok = 1;//cout<<i<<" "<<j<<" "<<k<<endl;
                                        break;
                                    }
                            }
                            if(ok == 0)
                            {
                                dp[now][i] += dp[now - (1 << (i - 1))][j];
    //                            p(now),printf(" ");cout<<i<<" "<<j;printf(" ");p(now - (1 << (i - 1)));
    //                            puts("");
                                dp[now][i] %= mod;
                            }
                        }
                    }
                }
            }
            int tot = 0;
            duke(i,0,n - 1)
            {
                if((now & (1 << i)) != 0)
                tot++;
            }
            if(tot >= 4)
            {
                duke(i,1,n)
                {
                    if((now & (1 << (i - 1))) != 0)
                    ans += dp[now][i],ans %= mod;
                }
            }
        }
    //    ans += 1;
    //    ans /= 2;
        /*duke(i,0,(1 << n) - 1)
        {
            duke(j,1,n)
            if((i & (1 << (j - 1))) != 0)
            p(i),printf(" "),cout<<dp[i][j]<<endl;
        }*/
        printf("%d
    ",ans);
        return 0;
    }

    代码:

  • 相关阅读:
    常用正则
    css换行与不换
    数组Array.prototype方法的使用
    你真的知道css三种存在样式(外联样式、内部样式、内联样式)的区别吗?
    js中批量处理样式——cssText的使用
    CSS的定位属性实现text-shadow属性的文本下产生阴影效果
    深入js的面向对象学习篇(继承篇)——温故知新(三)
    深入js的面向对象学习篇(封装是一门技术和艺术)——温故知新(二)
    深入js的面向对象学习篇——温故知新(一)
    【转链接】Handlebars模板引擎以及浅谈模板引擎的实现原理
  • 原文地址:https://www.cnblogs.com/DukeLv/p/10503723.html
Copyright © 2020-2023  润新知