题意:给你一个n*n的用火柴棍拼成的正方形,然后在这个正方一开始先取走m个火柴棍,问你剩下的最少取走多少个可以使这个这些火柴无法构成正方形。
思路:这个题知道是IDA*搜索,可是这个题最大的问题就是把所有的正方形都找出来,现在代码能力太弱了,这个东西写了两个小时都没写出来,最后借鉴了别人的把这个写了出来,剩下的就是枚举删除剩下的正方形每一个边,然后迭代加深搜索还有估值函数,我看了一下最初的图,发现一个边最多能破坏n + 1个正方形,以此作为估值函数,然后抱着试试看的想法交了一下,竟然过了。
PS:代码能力还是有待加强,这个题还可以用DLX,以后学习一下再做一下这个题。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <list>
#define MAXN 100
#define INF 10000000
#define MOD 1000000007
#define LL long long
#define pi acos(-1.0)
using namespace std;
int n, m;
int ans;
bool link[MAXN];
int is_square[MAXN];
vector<int> square[MAXN];
vector<int> stick[MAXN];
int totsquare;
int totstick;
int h() {
int cnt = 0;
for (int i = 1; i <= totsquare; ++i) {
if (is_square[i] == 0)
cnt++;
}
return cnt;
}
bool dfs(int x, int maxn) {
if ((n + 1) * x + h() >= maxn * (n + 1))
return false;
int cnt = 1;
while (is_square[cnt] < 0 && cnt <= totsquare)
cnt++;
if (cnt > totsquare) {
ans = min(x, ans);
return true;
}
for (int i = 0; i < square[cnt].size(); ++i) {
int num = square[cnt][i];
if (link[num]) {
for (int j = 0; j < stick[num].size(); ++j) {
is_square[stick[num][j]]--;
}
link[num] = false;
if (dfs(x + 1, maxn))
return true;
link[num] = true;
for (int j = 0; j < stick[num].size(); ++j) {
is_square[stick[num][j]]++;
}
}
}
return false;
}
int main() {
std::ios::sync_with_stdio(false);
int T;
cin >> T;
for (int kase = 1; kase <= T; ++kase) {
memset(square, 0, sizeof(square));
memset(stick, 0, sizeof(stick));
cin >> n;
m = 2 * n * (n + 1);
int num, x;
for (int i = 1; i <= m; ++i) {
link[i] = true;
}
cin >> num;
int neibor = 2 * n + 1;
totsquare = 0;
totstick = 2 * n * (n + 1);
for (int sz = 1; sz <= n; sz++) {
for (int i = 1; (i - 1) / neibor + sz <= n; i += neibor) {
for (int j = i; j - i + sz <= n; j++) {
totsquare++;
for (int l = j; l - j < sz; l++) {
square[totsquare].push_back(l);
square[totsquare].push_back(l + sz * neibor);
stick[l].push_back(totsquare);
stick[l + sz * neibor].push_back(totsquare);
}
for (int l = j + n; (l - j - sz) / neibor < sz; l += neibor) {
square[totsquare].push_back(l);
square[totsquare].push_back(l + sz);
stick[l].push_back(totsquare);
stick[l + sz].push_back(totsquare);
}
}
}
}
memset(is_square, 0, sizeof(is_square));
for (int i = 0; i < num; ++i) {
cin >> x;
link[x] = false;
for (int j = 0; j < stick[x].size(); ++j) {
is_square[stick[x][j]]--;
}
totstick--;
}
ans = INF;
for (int i = 0; ; ++i) {
if (dfs(0, i))
break;
}
cout << ans << endl;
}
return 0;
}
/*
2
2
0
3
3 12 17 23
*/