愤怒的小鸟

来源 : https://www.acwing.com/problem/content/526/

**dancing links **

该题为找到最少的抛物线覆盖所有坐标

#include <bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
inline int lowbit(int x) { return x & (-x); }
#define ll long long
#define pb push_back
#define PII pair<int, int>
#define fi first
#define se second
#define inf 0x3f3f3f3f
typedef pair<double, double> PDD;
const int N = 18, M = 1 << 18;
const double eps = 1e-8;
int n, m;
PDD q[N];
int path[N][N];
int f[M];

int cmp(double x1, double x2) {
    if (fabs(x1 - x2) < eps) return 0;
    if (x1 < x2) return -1;
    return 1;
}

int main() {
    IO;
    int _;
    cin >> _;
    while (_--) {
        cin >> n >> m;
        for (int i = 0; i < n; ++i) cin >> q[i].fi >> q[i].se;
        
        memset(path, 0, sizeof path);
        for (int i = 0; i < n; ++i) {
            path[i][i] = 1 << i;
            for (int j = 0; j < n; ++j) {
                double x1 = q[i].fi, y1 = q[i].se;
                double x2 = q[j].fi, y2 = q[j].se;
                if (!cmp(x1, x2)) continue;
                double a = (y1 / x1 - y2 / x2) / (x1 - x2);
                double b = y1 / x1 - a * x1;
                if (cmp(a, 0) >= 0) continue;
                int state = 0;
                for (int k = 0; k < n; ++k) {
                    double x = q[k].fi, y = q[k].se;
                    if (!cmp(a * x * x + b * x, y)) state += 1 << k;
                }
                path[i][j] = state;
            } 
        }
        
        memset(f, 0x3f, sizeof f);
        f[0] = 0;
        for (int i = 0; i + 1 < 1 << n; ++i) {
            int x = 0;
            for (int j = 0; j < n; ++j) 
                if (!(i >> j & 1)) {
                    x = j;
                    break;
                }
            for (int j = 0; j < n; ++j)
                f[i | path[x][j]] = min(f[i | path[x][j]], f[i] + 1);
        } 

        cout << f[(1 << n) - 1] << endl;
    } 

    return 0;
}
posted @ 2021-01-25 15:37  phr2000  阅读(35)  评论(0编辑  收藏  举报