//刚开始TLE了...然后改成启发式搜索(必须<=,只有<也会TLE)WA了
区别可能是AC代码只需要在找到选择一行的时候,只删去这一行上所有点的列
WA代码的删除部分则是//删去所有与当前行中1相互矛盾的行即for循环删去该行j列中所有1的行(除了num本身)
AC代码:
#include <iostream>
#include <cstdio>
#include<cstring>
using namespace std;
const int maxm=15*15+5;//最大列数
const int maxn=15*15+5;//最大行数
const int maxnode=maxm*maxn;//最大节点数
const int inf = 0x3f3f3f3f;
class dlx {
public:
int n,m,size;
int R[maxnode],L[maxnode],U[maxnode],D[maxnode],col[maxnode],H[maxn],row[maxnode],S[maxm];
//表示最后选中的行的数量,ans记录答案
int res,ans[maxn];
void init(int x,int y) {
n=x;
m=y;
res = inf;
int i;
for(i=0; i<=m; i++) {
S[i]=0;
U[i]=i;
D[i]=i;
L[i]=i-1;
R[i]=i+1;
}
L[0]=m;
R[m]=0;
size=m;
for(i=0; i<=n; i++) {
H[i]=-1;
}
}
void link(int r,int c) {
size++;
col[size]=c;
row[size]=r;
S[col[size]]++;
U[size]=c;
D[size]=D[c];
U[D[c]]=size;
D[c]=size;
if(H[r]<0) {
H[r]=L[size]=R[size]=size;
} else {
R[size]=R[H[r]];
L[size]=H[r];
L[R[H[r]]]=size;
R[H[r]]=size;
}
}
void remove(int c) {
for(int i = D[c]; i != c; i = D[i]) {
L[R[i]] = L[i];
R[L[i]] = R[i];
}
}
void resume(int c) {
for(int i = U[c]; i != c; i = U[i]) {
L[R[i]] = R[L[i]] = i;
}
}
bool v[maxn];
int f() {
int h = 0;
for(int c = R[0]; c != 0; c = R[c])
v[c] = true;
for(int c = R[0]; c != 0; c = R[c]) {
if(v[c]) {
h ++;
v[c] = false;
for(int i = D[c]; i != c; i = D[i]) {
for(int j = R[i]; j != i; j = R[j])
v[col[j]] = false;
}
}
}
return h;
}
void dance(int cnt) {
if(cnt+f() >= res) return;//A*
//当原点的右边结点是自己时,所有的已经全部删除完毕,符合条件
if(R[0]==0) {
res=min(res, cnt);
return;
}
int cur;
cur=R[0];
for(int i=cur; i!=0; i=R[i]) {
if(S[cur]>S[i]) {
cur=i;
}
}
int i,j;
for(i=D[cur]; i!=cur; i=D[i]) {//只删去这一行上所有点的列
remove(i);
for(j=R[i]; j!=i; j=R[j]) {
remove(j);
}
dance(cnt+1);
for(j=L[i]; j!=i; j=L[j]) {
resume(j);
}
resume(i);
}
return;
}
};
dlx g;
int a[20][20];
int id[20][20];
int main() {
int n, m;
while(~scanf("%d%d",&n,&m)) {
int sz = 0;
memset(id,0,sizeof(id));
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
scanf("%d", &a[i][j]);
if(a[i][j] == 1) id[i][j] = (++sz);
}
}
g.init(n * m, sz);
sz = 1;
int n1, m1;
scanf("%d%d", &n1, &m1);
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
for(int x = 0; x < n1 && i + x < n; x ++) {
for(int y = 0; y < m1 && j + y < m; y ++) {
if(id[i + x][j + y])
g.link(sz,id[i + x][j + y]);
}
}
sz ++;
}
}
g.dance(0);
printf("%d\n", g.res);
}
return 0;
}
//WA代码
#include <iostream>
#include <cstdio>
#include<cstring>
using namespace std;
const int maxm=15*15+5;//最大列数
const int maxn=15*15+5;//最大行数
const int maxnode=maxm*maxn;//最大节点数
const int inf = 0x3f3f3f3f;
class dlx {
public:
int n,m,size;
int R[maxnode],L[maxnode],U[maxnode],D[maxnode],col[maxnode],H[maxn],row[maxnode],S[maxm];
//表示最后选中的行的数量,ans记录答案
int res,ans[maxn];
void init(int x,int y) {
n=x;
m=y;
res = inf;
int i;
for(i=0; i<=m; i++) {
S[i]=0;
U[i]=i;
D[i]=i;
L[i]=i-1;
R[i]=i+1;
}
L[0]=m;
R[m]=0;
size=m;
for(i=0; i<=n; i++) {
H[i]=-1;
}
}
void link(int r,int c) {
size++;
col[size]=c;
row[size]=r;
S[col[size]]++;
U[size]=c;
D[size]=D[c];
U[D[c]]=size;
D[c]=size;
if(H[r]<0) {
H[r]=L[size]=R[size]=size;
} else {
R[size]=R[H[r]];
L[size]=H[r];
L[R[H[r]]]=size;
R[H[r]]=size;
}
}
void remove(int c) {
R[L[c]]=R[c];
L[R[c]]=L[c];
int x,y;
for(x=D[c]; x!=c; x=D[x]) {
for(y=R[x]; y!=x; y=R[y]) {
D[U[y]]=D[y];
U[D[y]]=U[y];
S[col[y]]--;
}
}
}
void resume(int c) {
int i,j;
for(i=U[c]; i!=c; i=U[i]) {
for(j=L[i]; j!=i; j=L[j]) {
U[D[j]]=j;
D[U[j]]=j;
S[col[j]]++;
}
}
L[R[c]]=R[L[c]]=c;
}
bool v[maxn];
int f() {
int h = 0;
for(int c = R[0]; c != 0; c = R[c])
v[c] = true;
for(int c = R[0]; c != 0; c = R[c]){
if(v[c]){
h ++;
v[c] = false;
for(int i = D[c]; i != c; i = D[i]) {
for(int j = R[i]; j != i; j = R[j])
v[col[j]] = false;
}
}
}
return h;
}
void dance(int cnt)
{
if(cnt+f() >= res) return;//A*
//当原点的右边结点是自己时,所有的已经全部删除完毕,符合条件
if(R[0]==0) {
res=min(res, cnt);
return;
}
int cur;
cur=R[0];
for(int i=cur; i!=0; i=R[i]) {
if(S[cur]>S[i]) {
cur=i;
}
}
remove(cur);
int i, j;
for(i=D[cur]; i!=cur; i=D[i]) {
for(j=R[i]; j!=i; j=R[j]) {
remove(col[j]);
}
dance(cnt+1);
for(j=L[i]; j!=i; j=L[j]) {
resume(col[j]);
}
}
resume(cur);
return;
}
};
dlx g;
int a[20][20];
int id[20][20];
int main() {
int n, m;
while(~scanf("%d%d",&n,&m)) {
int sz = 0;
memset(id,0,sizeof(id));
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
scanf("%d", &a[i][j]);
if(a[i][j] == 1) id[i][j] = ++sz;
}
}
g.init(n * m,sz);
sz = 1;
int n1, m1;
scanf("%d%d", &n1, &m1);
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
for(int x = 0; x < n1 && i + x < n; x ++) {
for(int y = 0; y < m1 && j + y < m; y ++) {
if(id[i + x][j + y])
g.link(sz,id[i + x][j + y]);
}
}
sz ++;
}
}
g.dance(0);
printf("%d\n", g.res);
}
return 0;
}