HDU 4739 Zhuge Liang's Mines 暴力搜索

题目链接

看了题目,因为n很小,最多20,第一反应是状压dp,首先预处理可能构成正方形的状态集合,然后背包算出来就行了,但是考量了一下复杂度,dp的状态是1<<20,然后当20个点是能构成的正方形的四个点,然后每个点重复5次,则能构成正方形的状态集合个数是4*4*4*4=256,dp转移的极限运算次数大概就是2亿,还是多组数据,果断换思路。不过下来发现很多都是状压dp过的,看来数据应该没有故意卡这种极限情况。

这里用dfs来写会更快,dfs之前,先将点按照y从小到大,x从小到大的时候排序,则dfs处理这个点的时候,这个点如果能构成,则一定是正方形的左下点,然后在枚举y值相同的,x更大的点,根据这两个点就能算出其他两个点的位置,然后回溯就行。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 using namespace std;
 5 const int maxn = 22;
 6 int n, x[maxn], y[maxn], a[maxn], ans, vis[maxn];
 7 int mp[210][210];
 8 int cmp(int i, int j) {
 9     if (y[i] != y[j])
10         return y[i] < y[j];
11     return x[i] < x[j];
12 }
13 void dfs(int dep) {
14     if (dep * 4 > ans)
15         ans = dep << 2;
16     for (int i = 0; i < n; ++i)
17         if (!vis[i])
18             for (int j = i + 1; j < n; ++j)
19             if (!vis[j]) {
20                 int ii = a[i], jj = a[j];
21                 if (y[ii] == y[jj] && x[ii] < x[jj]) {
22                     int d = x[jj] - x[ii], k, l;
23                     for (k = j + 1; k < n && !(x[a[k]] == x[ii] && y[a[k]] == y[ii] + d && !vis[k]); ++k);
24                     for (l = j + 1; l < n && !(x[a[l]] == x[jj] && y[a[l]] == y[ii] + d && !vis[l]); ++l);
25                     if (k < n && l < n) {
26                         vis[i] = vis[j] = vis[k] = vis[l] = 1;
27                         dfs(dep + 1);
28                         vis[i] = vis[j] = vis[k] = vis[l] = 0;
29                     }
30                 }
31             }
32 }
33 int main() {
34     while (~scanf("%d", &n) && n != -1) {
35         memset(mp, 0, sizeof(mp));
36         for (int i = 0; i < n; ++i) {
37             scanf("%d%d", &x[i], &y[i]);
38             a[i] = i;
39             ++mp[x[i]][y[i]];
40         }
41         sort(a, a + n, cmp);
42         ans = 0;
43         memset(vis, 0, sizeof(vis));
44         dfs(0);
45         printf("%d\n", ans);
46     }
47     return 0;
48 }
View Code

 

转载于:https://www.cnblogs.com/Apiec/p/6063154.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值