1. 程式人生 > >洛谷 #2831. 憤怒的小鳥

洛谷 #2831. 憤怒的小鳥

題意

問最少用幾條從原點出發的拋物線

即 \(ax^2+bx=0\) 能消滅全部的pig

題解

我是用dfs寫的

對於每一個豬,檢測是否已被擊落,否則 暫時單獨 or 與其他單獨的豬組成拋物線

除錯記錄

有一個地方回溯忘記打了

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#define maxn 20
#define INF 0x3f3f3f3f

using namespace std;

int T,
n, ans, tot = 0, totp = 0; double tx[maxn], ty[maxn], px[maxn], py[maxn], x[maxn], y[maxn]; bool equ(double a, double b){ if (fabs(a - b) < 1e-8) return true; return false; } void del(int pos){ for (int j = pos; j < tot; j++) tx[j] = tx[j + 1], ty[j] = ty[j + 1]; tot--; } void
insert(int pos, double x, double y){ for (int j = tot; j >= pos; j--) tx[j + 1] = tx[j], ty[j + 1] = ty[j]; tot++; tx[pos] = x, ty[pos] = y; } bool pass(int dep){ for (int k = 1; k <= totp; k++) if (equ(px[k] * x[dep] * x[dep] + py[k] * x[dep], y[dep])) return true; return
false; } void dfs(int dep){ // printf("%d %d\n", tot, totp); if (tot + totp >= ans) return; if (dep == n + 1){ ans = min(ans, tot + totp); return; } if (pass(dep)){ dfs(dep + 1); return; } double x1 = x[dep], y1 = y[dep], x2 = 0, y2 = 0; for (int i = 1; i <= tot; i++){ x2 = tx[i], y2 = ty[i]; if (equ(x1, x2)) continue; double a = (x2 * y1 - x1 * y2) / (x1 * x1 * x2 - x1 * x2 * x2); double b = (x1 * x1 * y2 - x2 * x2 * y1) / (x1 * x2 * (x1 - x2)); if (a < 0){ px[++totp] = a, py[totp] = b; double ttx = tx[i], tty = ty[i]; del(i); dfs(dep + 1); insert(i, ttx, tty); px[totp] = 0, py[totp--] = 0; } } tx[++tot] = x[dep], ty[tot] = y[dep]; dfs(dep + 1); tx[tot] = 0, ty[tot--] = 0; } int main(){ scanf("%d", &T); while (T--){ int opt; scanf("%d%d", &n, &opt); for (int i = 1; i <= n; i++) scanf("%lf%lf", &x[i], &y[i]); ans = INF; totp = 0; memset(px, 0, sizeof px), memset(py, 0, sizeof py); tot = 0; memset(tx, 0, sizeof tx), memset(ty, 0, sizeof ty); dfs(1); printf("%d\n", ans); } return 0; }