HDU 4739 Zhuge Liang's Mines (状态压缩+背包DP)

题意

给定平面直角坐标系内的N(N <= 20)个点,每四个点构成一个正方形可以消去,问最多可以消去几个点。

思路

比赛的时候暴力dfs+O(n^4)枚举写过了……无意间看到有题解用状压DP(这才是正解吧T_T),然后自己才恍然大悟- -…… 点不多嘛,用一个20位的整数表示各个点。先O(n^4)枚举出所有正方形情况,然后把这20位当背包,每种情况的二进制位当物品,做01背包就可以了. 似乎遇到N = 10+、20+的都应该想想状态压缩>.<……

代码

  [cpp] #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <queue> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i, begin, end) for (int i = begin; i <= end; i ++) using namespace std; vector <int> v; struct Point{ int x, y; }p[25]; bool cmp(Point p1, Point p2){ if (p1.x == p2.x) return p1.y < p2.y; else return p1.x < p2.x; } int dp[1050000]; int main(){ int n; while(scanf("%d", &n)){ if (n < 0) break; for (int i = 0; i < n; i ++){ scanf("%d %d", &p[i].x, &p[i].y); } sort(p, p+n, cmp); v.clear(); for (int i = 0; i < n; i ++) for (int j = i + 1; j < n; j ++) if (p[i].x == p[j].x){ int dy = abs(p[i].y - p[j].y); for (int k = j + 1; k < n; k ++) if (p[k].y == p[i].y && p[k].x == p[i].x + dy) for (int l = k + 1; l < n; l ++){ if (p[l].y == p[j].y && p[l].x == p[i].x + dy) v.push_back((1<<i)|(1<<j)|(1<<k)|(1<<l)); } } MEM(dp, 0); int res = 0; for (int i = 0; i < (int)v.size(); i ++){ for (int mk = (1<<n)-1; mk >= 0; mk --){ if ((mk & v[i]) == v[i]) dp[mk] = max(dp[mk], dp[mk-v[i]]+4); res = max(res, dp[mk]); } } printf("%d\n", res); } return 0; } [/cpp]

转载于:https://www.cnblogs.com/AbandonZHANG/p/4114125.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值