來源:重慶一中
這道題其實顯然是搜索,只不過我看到20*20的數據範圍覺得搜索不穩,亂想了比較久,最後只交了個非常暴力的搜索,而且爆零了。搜索是弱項,還需好好加強。
20*20,理論上來說有
所以其實是跑得飛快的。
#include<stdio.h>
int M,N,Black,row[25][25],col[25][25],Tr[25],Tc[25];
//Tr記錄某一行的黑色塊總數,Tc記錄某一列的黑色塊總數
int Map[25][25];
bool cr(int x,int r)//檢查第x行0~r位置是否合法
{
int i,tot=0,Now=1,tmp=0;
for(i=0;i<=r;i++)
{
if(Map[x][i])
{
tmp++;tot++;
if(tmp>row[x][Now])return false;
}
else if(tmp)
{
if(tmp!=row[x][Now])return false;
tmp=0;Now++;
}
}
if(tot+M-r-1<Tr[x])return false;//剩下的位置全部填滿也不行,不合法
if(tot>Tr[x])return false;//多了,不合法
return true;
}
bool cc(int x,int r)//檢查第x列0~r位置是否合法,基本上和cr函數一樣
{
int i,tot=0,Now=1,tmp=0;
for(i=0;i<=r;i++)
{
if(Map[i][x])
{
tmp++;tot++;
if(tmp>col[x][Now])return false;
}
else if(tmp)
{
if(tmp!=col[x][Now])return false;
tmp=0;Now++;
}
}
if(tot+N-r-1<Tc[x])return false;
if(tot>Tc[x])return false;
return true;
}
bool Find;
void DFS(int cur,int rem)//cur:當前討論到的格子的編號,從0開始;rem:剩下的黑色塊的數量
{
if(Find)return;
int i,x,y;
if(cur)
{
x=(cur-1)/M;y=(cur-1)%M;
if(!cr(x,y))return;
for(i=0;i<=y;i++)if(!cc(i,x))return;
}
if(cur==N*M)
{
int i,j;
for(i=0;i<N;i++,putchar('\n'))
for(j=0;j<M;j++)
{
if(Map[i][j])putchar('#'),putchar('#');
else putchar(' '),putchar(' ');
}
Find=true;
return;
}
if(rem==-1)return;
x=cur/M;y=cur%M;
Map[x][y]=1;
DFS(cur+1,rem-1);
Map[x][y]=0;
DFS(cur+1,rem);
}
int main()
{
int i,x;
scanf("%d%d",&M,&N);
for(i=0;i<M;i++)
{
scanf("%d",&x);
while(x)
{
col[i][++col[i][0]]=x;Black+=x;Tc[i]+=x;
scanf("%d",&x);
}
}
for(i=0;i<N;i++)
{
scanf("%d",&x);
while(x)
{
row[i][++row[i][0]]=x;Tr[i]+=x;
scanf("%d",&x);
}
}
DFS(0,Black);
}