今天的网络赛题目,用状态压缩的思想预处理,可以证明出20个点大概不能组成超过100个正方形。于是先预处理所有的正方形,然后0-1背包就可以了。、
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<algorithm> #include<iostream> #include<cstring> #include<fstream> #include<sstream> #include<vector> #include<string> #include<cstdio> #include<bitset> #include<queue> #include<stack> #include<cmath> #include<map> #include<set> #define FF(i, a, b) for(int i=a; i<b; i++) #define FD(i, a, b) for(int i=a; i>=b; i--) #define REP(i, n) for(int i=0; i<n; i++) #define CLR(a, b) memset(a, b, sizeof(a)) #define debug puts("**debug**") #define LL long long #define PB push_back #define MP make_pair #define eps 1e-10 using namespace std; const int N = 22; struct Point { int x, y; bool operator < (const Point& rhs) const { return x < rhs.x || (x == rhs.x && y < rhs.y); } }p[N]; int n, dp[1 << N]; bool vis[1 << N]; vector<int> sqr; bool ok(int i, int j, int k, int s) { return (p[i].x == p[j].x && p[i].y == p[k].y && p[j].y == p[s].y && p[s].x == p[k].x) && (p[k].x - p[i].x == p[j].y - p[i].y); } void pre() { int i, j, k, s; sqr.clear(); for(i = 0; i < n; i ++) for(j = i + 1; j < n; j ++) for(k = j + 1; k < n; k ++) for(s = k + 1; s < n; s ++) if(ok(i, j, k, s)) sqr.PB((1 << i) + (1 << j) + (1 << k) + (1 << s)); } int main() { //freopen("input.txt", "r", stdin); int i, j, ans; while(scanf("%d", &n), n > 0) { for(i = 0; i < n; i ++) { scanf("%d%d", &p[i].x, &p[i].y); } sort(p, p + n); pre(); CLR(dp, -1); dp[0] = 0, ans = 0; for(i = 0; i < sqr.size(); i ++) { for(j = 0; j < (1 << n); j ++) { if(((j & sqr[i]) == 0) && dp[j] != -1) { dp[j | sqr[i]] = max(dp[j | sqr[i]], dp[j] + 1); ans = max(dp[j + sqr[i]], ans); } } } printf("%d ", ans * 4); } }