hdu 4739【位运算】.cpp

时间:2022-10-06 04:40:27

题意:

给出n个地雷所在位置,正好能够组成正方形的地雷就可以拿走..为了简化题目,只考虑平行于横轴的正方形..

问最多可以拿走多少个正方形..

思路:

  先找出可以组成正方形的地雷组合cnt个..

  然后st = 1<<cnt..

  用位运算来考虑取哪一个组合可以拿走最多的地雷且满足题目条件..

Tips:

  题目比较烦恼的地方是解决:

  ①. 所选集合里面的地雷会不会重复拿..

  ②. 所选集合里面在同一个地方取走的地雷会不会比该地方题目给出的地雷数多..

  同一个地点可能有多个地雷,如果用去重就不好算多个正方形在同一个位置的情况..

  所以不去重,但是在计算组合的时候要考虑某一个地点的地雷取了多少次,是否比题目给出的该地点的地雷数少..

Code:

 /******************************************
*Author: Griselda
*Created Time: 2013-11-25 15:26
*Filename: 4739.cpp
* ****************************************/
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std; struct Point
{
int x;
int y;
}p[]; struct Set
{
Point p[];
int sta;
}s[]; int cnt, tmp;
int G[][];
int cmp(Point a, Point b)
{
if (a.x != b.x) return a.x < b.x;
else return a.y < b.y;
} bool check(int a, int b, int c, int d)
{
if (p[a].x == p[b].x &&
p[c].x == p[d].x &&
p[a].y == p[c].y &&
p[b].y == p[d].y &&
(p[c].x-p[a].x == p[b].y - p[a].y))
return true;
else return false;
} bool check2(int st)
{
int psum[][], tt = ;
memset(psum, , sizeof(psum));
tmp = ;
for (int i = ; i < cnt; ++i)
if (st&(<<i) && !(tt&s[i].sta)) {
tmp++;
tt |= s[i].sta;
int x1 = s[i].p[].x, y1 = s[i].p[].y, x2 = s[i].p[].x, y2 = s[i].p[].y, x3 = s[i].p[].x, y3 = s[i].p[].y, x4 = s[i].p[].x, y4 = s[i].p[].y;
psum[x1][y1]++, psum[x2][y2]++, psum[x3][y3]++, psum[x4][y4]++;
if (psum[x1][y1] > G[x1][y1] || psum[x2][y2] > G[x2][y2] || psum[x3][y3] > G[x3][y3] || psum[x4][y4] > G[x4][y4]) return false;
} else if (st&(<<i) && (tt&s[i].sta)) return false;
return true;
} int main()
{
// freopen("in.txt", "r", stdin);
int n;
int st;
int ans;
while (~scanf("%d", &n)) {
if (n == -) break;
if (n < ) {
puts("");
for (int i = ; i < n; ++i)
scanf("%*d %*d");
continue;
}
memset(G, , sizeof(G));
ans = cnt = ;
for (int i = ; i < n; ++i) {
scanf("%d %d", &p[i].x, &p[i].y);
G[p[i].x][p[i].y]++;
}
sort(p, p+n, cmp); for (int i = ; i < n-; ++i)
for (int j = i+; j < n-; ++j)
for (int k = j+; k < n-; ++k)
for (int l = k+; l < n; ++l)
if (check(i, j, k, l)) {
s[cnt].p[] = p[i], s[cnt].p[] = p[j], s[cnt].p[] = p[k], s[cnt].p[] = p[l];
s[cnt].sta = |(<<i)|(<<j)|(<<k)|(<<l);
cnt++;
}
st = <<cnt;
for (int i = ; i < st; ++i)
if (check2(i)) ans = max(ans, tmp);
printf("%d\n", ans*);
}
return ;
}

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4739