题目:http://acm.hdu.edu.cn/showproblem.php?pid=4739
题目大意:二维平面给你n个点,4个能组成一个正方形的点能一起消除,问你最多能消除几个?
思路:因为只有20个点,就状压一下,然后就是 d[ s|s1 ] |= d[ s1 ],这里s1是某4个能组成正方形的点且不包含在s里面,读入的时候处理一下s1就可以了。可以直接dfs过去,找到最长路径就好了。
自己做的时候,是枚举状态这样做的,先开始由于没有没有去处理s1,而是枚举所有四个点的状态,然后再去判断,一直TLE。。。然后优化优化,最后终于优化到了这一步。。挺简单的优化,为什么最先开始会没想到。。。 = =
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 22;
struct Point
{
int x,y;
bool operator < (const Point & tmp) const
{
if(x == tmp.x) return y < tmp.y;
else return x < tmp.x;
}
} p[MAXN];
int is_sq(int a,int b,int c,int d)
{
if(p[a].x== p[b].x)
{
int l1 = p[b].y - p[a].y;
if(p[b].y == p[d].y)
{
int l2 = p[d].x - p[b].x;
if(l1 == l2 && p[a].y == p[c].y)
{
int l3 = p[c].x- p[a].x;
if(l2 == l3 && p[c].x == p[d].x)
{
int l4 = p[d].y - p[c].y;
if(l3 == l4)
return 1;
}
}
}
}
return 0;
}
int tot;
int sta[5555];
bool vis[1<<22];
int ans;
void dfs(int s,int cnt)
{
//printf("s = %d,cnt = %d\n",s,cnt);
ans = max(ans,cnt);
vis[s] = 1;
for(int i = 0;i < tot;i++)
{
if((sta[i]&s) == 0 && !vis[s|sta[i]])
{
dfs(s|sta[i],cnt + 4);
}
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n == -1) break;
for(int i = 0;i<n;i++)
scanf("%d%d",&p[i].x,&p[i].y);
sort(p,p+n);
tot=0;
for(int i = 0;i<n;i++)
for(int j = i+1;j<n;j++)
for(int k = j+1;k<n ;k++)
for(int l = k+1;l<n;l ++)
{
if(is_sq(i,j,k,l))
{
sta[tot++] = (1<<i) + (1<<j) + (1<<k) + (1<<l);
}
}
ans = 0;
//printf("tot = %d\n",tot);
memset(vis,0,sizeof(vis));
dfs(0,0);
printf("%d\n",ans);
}
return 0;
}