• [CQOI 2018]解锁屏幕


    Description

    题库链接

    给出平面上 (n) 个点,一开始你可以选任何一个点作为起点,接着对于每一个你在的位置,你可以选取一个未走过的点。将路径(线段)上所有的点均选上(包括起点终点),并走到选择的那个点上。询问选的点的个数 (geq 4) 的方案数。区别不同的方案,只需要路径不一样即可。

    (1leq nleq 20)

    Solution

    状压 (dp)

    先预处理出两点间路径上会经过的点。 (dp) 的时候需要选择路径上不会经过未选择点的方案走。

    复杂度 (O(n^3+2^nn^2))

    Code

    #include <bits/stdc++.h>
    #define lowbit(x) ((x)&(-(x)))
    using namespace std;
    const int N = 20+5, SIZE = (1<<20)+5, yzh = 100000007;
    
    struct point {
        int x, y;
        point (int _x = 0, int _y = 0) {x = _x, y = _y; }
        point operator - (const point &b) const {return point(x-b.x, y-b.y); }
        int operator * (const point &b) const {return x*b.y-y*b.x; }
    }a[N];
    int n, mp[N][N], bin[N], f[SIZE][N], cnt[SIZE], ans;
    
    void check(int x, int y) {
        int mxx = max(a[x].x, a[y].x), mnx = min(a[x].x, a[y].x);
        int mxy = max(a[x].y, a[y].y), mny = min(a[x].y, a[y].y);
        for (int i = 1; i <= n; i++)
            if (i != x && i != y)
                if ((a[y]-a[x])*(a[i]-a[x]) == 0)
                    if (a[i].x >= mnx && a[i].x <= mxx && a[i].y >= mny && a[i].y <= mxy)
                    mp[x][y] |= bin[i-1];
    }
    void work() {
        scanf("%d", &n);
        bin[0] = 1; for (int i = 1; i <= n; i++) bin[i] = bin[i-1]<<1;
        for (int i = 1; i <= bin[n]; i++) cnt[i] = cnt[i-lowbit(i)]+1;
        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++) check(i, j);
        f[0][0] = 1;
        for (int i = 0; i < bin[n]; i++)
            for (int j = 0; j <= n; j++) if (f[i][j])
                for (int k = 1; k <= n; k++) if (!(bin[k-1]&i)) {
                    int x = j, y = k; if (x > y) swap(x, y);
                    if ((i&mp[x][y]) == mp[x][y]) (f[i|bin[k-1]][k] += f[i][j]) %= yzh;
                }
        for (int i = 0; i < bin[n]; i++) if (cnt[i] >= 4)
            for (int j = 1; j <= n; j++) (ans += f[i][j]) %= yzh;
        printf("%d
    ", ans);
    }
    int main() {work(); return 0; }
  • 相关阅读:

    队列
    Collection类
    Hashtable类、IdentityHashMap和WeakHashMap类
    LinkedHashMap类
    广播的种类:有序广播和无序广播
    自定义的BroadCastReceiver
    String的两个API,判断指定字符串是否包含另一字符串,在字符串中删除指定字符串。
    BroadcastReceiver的最简单用法
    Notification通知栏
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8989688.html
Copyright © 2020-2023  润新知