Problem 1686 神龙的难题
Accept: 444 Submit: 1365
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
Input
Output
Sample Input
4 41 0 0 10 1 1 00 1 1 01 0 0 12 24 4 0 0 0 00 1 1 00 1 1 00 0 0 02 2
Sample Output
41
Source
FOJ月赛-2009年2月- TimeLoop
重复覆盖的模板,A得第二道DLX。在精确覆盖的基础上改了好久,主要是这题时间压的比较紧。必须各种剪枝。
思路参考的别人,十分巧妙。这里直接粘贴。
把原矩阵中的1编号,一共有size个,那么建立新矩阵的列数就为size,因为原矩阵n*m,所以神龙每一次攻击攻击点一共有n*m个,这里攻击点可以看作每个攻击范围小矩阵的左上角那个点,因为攻击范围小矩阵最少是1*1, 也就是最多攻击n*m次, 所以新矩阵的行数为n*m, 也就是以攻击次数作为行,怪物的个数作为列,每一行上的1(每一次攻击)代表该攻击所能消灭的怪物,那么原问题也就转化为了 构造出来的新矩阵中最少选多少行(发动几次攻击), 这些行再组成的新矩阵中每一列至少有1个1 (因为要把所有的怪物都杀死,而且两次攻击的范围可能有重叠,一个怪物可以被两次攻击覆盖掉,也就是每列可以有多个1)。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 16*16
#define M 16*16
#define maxn 16*16*16*16
#define INF 0x3f3f3f3f
int L[maxn],R[maxn],U[maxn],D[maxn],Row[maxn],Col[maxn];
int H[N],S[M],ansn;
void init(int n,int m)
{
for(int i=0; i<=m; i++)
{
S[i]=0;
L[i]=i-1;
R[i]=i+1;
U[i]=D[i]=i;
}
L[0]=m;
R[m]=0;
for(int i=0; i<=n; i++)
H[i]=-1;
}
void update(int n,int m,int t)
{
S[m]++;
Row[t]=n;
Col[t]=m;
D[t]=D[m];
U[D[m]]=t;
U[t]=m;
D[m]=t;
if(H[n]<0)
H[n]=L[t]=R[t]=t;
else
{
R[t]=R[H[n]];
L[R[H[n]]]=t;
L[t]=H[n];
R[H[n]]=t;
}
}
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[M];
int f()
{
int a=0;
for(int i=R[0];i!=0;i=R[i]) v[i]=true;
for(int i=R[0];i!=0;i=R[i])
{
if(v[i])
{
a++;
v[i]=false;
for(int j=D[i];j!=i;j=D[j])
{
for(int k=R[j];k!=j;k=R[k])
{
v[Col[k]]=false;
}
}
}
}
return a;
}
void dance(int k)
{
if(k+f()>=ansn) return;
int c=R[0];
if(c==0)
{
if(k<ansn) ansn=k;
return;
}
for(int i=R[0];i!=0;i=R[i])
if(S[i]<S[c])
c=i;
for(int i=D[c];i!=c;i=D[i])
{
Remove(i);
for(int j=R[i];j!=i;j=R[j])
Remove(j);
dance(k+1);
for(int j=L[i];j!=i;j=L[j])
Resume(j);
Resume(i);
}
}
int main()
{
int n,m,ans,t;
int n1,m1;
int a[16][16];
while(scanf("%d %d",&n,&m)!=EOF)
{
ans=0;
memset (a,0,sizeof(0));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
scanf("%d",&a[i][j]);
if(a[i][j]==1)
{
a[i][j]=++ans;
}
}
}
init(n*m,ans);
t=ans+1;
scanf("%d %d",&n1,&m1);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
for(int q=i;(q<=i+n1-1)&&(q<=n);q++)
{
for(int w=j;(w<=j+m1-1)&&(w<=m);w++)
{
if(a[q][w]!=0)
{
update((i-1)*m+j,a[q][w],t);
t++;
}
}
}
}
}
ansn=INF;
dance(0);
printf("%d\n",ansn);
}
return 0;
}
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 16*16
#define M 16*16
#define maxn 16*16*16*16
#define INF 0x3f3f3f3f
int L[maxn],R[maxn],U[maxn],D[maxn],Row[maxn],Col[maxn];
int H[N],S[M],ansn;
void init(int n,int m)
{
for(int i=0; i<=m; i++)
{
S[i]=0;
L[i]=i-1;
R[i]=i+1;
U[i]=D[i]=i;
}
L[0]=m;
R[m]=0;
for(int i=0; i<=n; i++)
H[i]=-1;
}
void update(int n,int m,int t)
{
S[m]++;
Row[t]=n;
Col[t]=m;
D[t]=D[m];
U[D[m]]=t;
U[t]=m;
D[m]=t;
if(H[n]<0)
H[n]=L[t]=R[t]=t;
else
{
R[t]=R[H[n]];
L[R[H[n]]]=t;
L[t]=H[n];
R[H[n]]=t;
}
}
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[M];
int f()
{
int a=0;
for(int i=R[0];i!=0;i=R[i]) v[i]=true;
for(int i=R[0];i!=0;i=R[i])
{
if(v[i])
{
a++;
v[i]=false;
for(int j=D[i];j!=i;j=D[j])
{
for(int k=R[j];k!=j;k=R[k])
{
v[Col[k]]=false;
}
}
}
}
return a;
}
void dance(int k)
{
if(k+f()>=ansn) return;
int c=R[0];
if(c==0)
{
if(k<ansn) ansn=k;
return;
}
for(int i=R[0];i!=0;i=R[i])
if(S[i]<S[c])
c=i;
for(int i=D[c];i!=c;i=D[i])
{
Remove(i);
for(int j=R[i];j!=i;j=R[j])
Remove(j);
dance(k+1);
for(int j=L[i];j!=i;j=L[j])
Resume(j);
Resume(i);
}
}
int main()
{
int n,m,ans,t;
int n1,m1;
int a[16][16];
while(scanf("%d %d",&n,&m)!=EOF)
{
ans=0;
memset (a,0,sizeof(0));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
scanf("%d",&a[i][j]);
if(a[i][j]==1)
{
a[i][j]=++ans;
}
}
}
init(n*m,ans);
t=ans+1;
scanf("%d %d",&n1,&m1);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
for(int q=i;(q<=i+n1-1)&&(q<=n);q++)
{
for(int w=j;(w<=j+m1-1)&&(w<=m);w++)
{
if(a[q][w]!=0)
{
update((i-1)*m+j,a[q][w],t);
t++;
}
}
}
}
}
ansn=INF;
dance(0);
printf("%d\n",ansn);
}
return 0;
}