zoukankan      html  css  js  c++  java
  • [Luogu] P4460 [CQOI2018]解锁屏幕

    题目背景

    使用过Android 手机的同学一定对手势解锁屏幕不陌生。Android 的解锁屏幕由3X3 个点组成,手指在屏幕上画一条线,将其中一些点连接起来,即可构成一个解锁图案。如下面三个例子所示:

    题目描述

    画线时还需要遵循一些规则:

    1. 连接的点数不能少于4 个。也就是说只连接两个点或者三个点会提示错误。

    2. 两个点之间的连线不能弯曲。

    3. 每个点只能“使用”一次,不可重复。这里的“使用”是指手指划过一个点,该点变绿。

    4. 两个点之间的连线不能“跨过”另一个点,除非那个点之前已经被“使用”过了。

    对于最后一条规则,参见下图的解释。左边两幅图违反了该规则; 而右边两幅图(分别为2->4-1-3-6 和6->5-4->1->9-2) 则没有违反规则,因为在“跨过”点时,点已经被“使用”过了。

    现在工程师希望改进解锁屏幕,增减点的数目,并移动点的位置,不再是一个九宫格形状,但保持上述画线的规则不变。请计算新的解锁屏幕上,一共有多少满足规则的画线方案。

    题目解析

    易证,Hsz是巨神。

    状压dp,把每个点的状态记录下来,然后转移的时候注意处理4条规则。

    复杂度很紧,注意常数

    Code

    我有个大胆的想法

    #include<bits/stdc++.h>
    using namespace std;const int mod = 100000007;
    int n,ans,dp[21][1<<20],mid[21][21],X[21],Y[21];
    inline bool judge(int a,int b,int c) {
        short xa=X[a],ya=Y[a],xb=X[b],yb=Y[b],xc=X[c],yc=Y[c];
        if((max(xa,xb)>=xc&&min(xa,xb)<=xc&&max(ya,yb)>=yc&&min(ya,yb)<=yc)) 
        return (float)(xa-xb)/(ya-yb)==(float)(xa-xc)/(ya-yc);return false;}
    int main(register unsigned long long __locate,register unsigned long long __loc) {
        scanf("%d",&n);for(register int i=0;i<n;i++) {scanf("%d%d",&X[i],&Y[i]);dp[i+1][1<<i]=1;}
        for(int i=0;i<n;i++) for(int j=0;j<n;j++) if(i^j) for(int k=0;k<n;k++) if((i^k)&&(j^k)) mid[i][j]|=judge(i,j,k)<<k;
        for(int i=1;i<(1<<n);i++) for(int j=0;j<n;j++) if((1<<j)&i) for(int k=0;k<n;k++) if(!((1<<k)&i))
        if((i&mid[j][k])==mid[j][k]) {dp[k+1][i|(1<<k)]+=dp[j+1][i];if(dp[k+1][i|(1<<k)]>=mod) dp[k+1][i|(1<<k)]-=mod;}
        for(int i=15;i<1<<n;i++) if(__builtin_popcount(i)>=4) for(int j=1;j<=n;j++) {if((1<<j-1)&i) ans+=dp[j][i];
        if(ans>=mod)ans-=mod;} printf("%d",ans);return 0;
    }
  • 相关阅读:
    怎么获取数组中的对象的某一项之和
    原型链
    js的事件循环(Eventloop) 机制/js的宏任务微任务执行顺序
    怎么替换数组中对象的属性
    求对象所有值的和
    sequelize中duplicating:false的使用
    WebSocket
    轮播

    ssl tsl
  • 原文地址:https://www.cnblogs.com/floatiy/p/9848521.html
Copyright © 2011-2022 走看看