不少狀壓 \(dp\) 的優化都是預處理合法的狀態/轉移?c++
#include<bits/stdc++.h> inline int pos(int S,int i) { return (S>>i)&1; } using namespace std; typedef long long ll; inline int read() { int out=0,fh=1; char jp=getchar(); while ((jp>'9'||jp<'0')&&jp!='-') jp=getchar(); if (jp=='-') fh=-1,jp=getchar(); while (jp>='0'&&jp<='9') out=out*10+jp-'0',jp=getchar(); return out*fh; } const int P=1e8+7; inline int add(ll a,int b) { return a+b>=P?a+b-P:a+b; } const int MAXN=20; int n,x[MAXN],y[MAXN]; int Cross[MAXN][MAXN]; int f[(1<<MAXN)+10][MAXN+10]; int ans=0; int count(int x) { int s=0; while(x) { s+=(x&1); x>>=1; } return s; } int main() { // freopen("data.in","r",stdin); n=read(); for(int i=0; i<n; ++i) x[i]=read(),y[i]=read(); 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 && x[i]<=x[k] && x[k]<=x[j] && y[i]<=y[k] && y[k]<=y[j] && (y[k]-y[i])*(x[k]-x[j])==(y[k]-y[j])*(x[k]-x[i])) { Cross[i][j]|=(1<<k); Cross[j][i]|=(1<<k); } } for(int i=0; i<n; ++i) f[1<<i][i]=1; int lim=(1<<n); for(int S=1; S<lim; ++S) for(int i=0; i<n; ++i) if(pos(S,i) && f[S][i]) { for(int j=0; j<n; ++j) if(pos(S,j)==0 && ((S&Cross[i][j])==Cross[i][j])) f[S|(1<<j)][j]=add(f[S|(1<<j)][j],f[S][i]); } for(int S=0; S<lim; ++S) if(count(S)>=4) { for(int i=0; i<n; ++i) ans=add(ans,f[S][i]); } cout<<ans<<endl; return 0; }