这题刚开始不懂题意,不懂样例怎么回事,只能百度看别人了,代码看懂了才理解样例怎么回事,原来输入的n,m是指拼图,不是指
拼好的图的行列数,而是指拼图的个数,这题直接爆搜肯定不行,要加剪枝,主要就是剪枝怎么加,先判断每面的F是否等于每面的长,
和每面的O和I是否匹配。然后爆搜判断是否相匹配就行。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<cmath>
#include<climits>
#include<vector>
#include<cfloat>
#include<queue>
#include<cctype>
#include<cstdlib>
#include<string>
#define LL long long
using namespace std;
int n,m;
string a[50],b[10][10];
int l,num[40];
bool Possible(int x,int y,int i)
{
if(x==1&&a[i][0]!='F') return 0;
if(x==n&&a[i][2]!='F') return 0;
if(y==1&&a[i][3]!='F') return 0;
if(y==m&&a[i][1]!='F') return 0;
if(x!=1&&a[i][0]=='F') return 0;
if(x!=n&&a[i][2]=='F') return 0;
if(y!=1&&a[i][3]=='F') return 0;
if(y!=m&&a[i][1]=='F') return 0;
if(b[x-1][y][2]=='I'&&a[i][0]!='O') return 0;
if(b[x-1][y][2]=='O'&&a[i][0]!='I') return 0;
if(b[x][y-1][1]=='I'&&a[i][3]!='O') return 0;
if(b[x][y-1][1]=='O'&&a[i][3]!='I') return 0;
return 1;
}
bool dfs(int x,int y)
{
if(y==m+1) return dfs(x+1,1);
if(x==n+1) return 1;
for(int i=0;i<l;i++)
{
if(num[i]&&Possible(x,y,i))
{
b[x][y]=a[i];
num[i]--;
if(dfs(x,y+1)) return 1;
b[x][y]="0000";
num[i]++;
}
}
return 0;
}
bool Pan()
{
int k[4][2]={0},kk[4]={0};
for(int i=0;i<n*m;i++)
{
for(int j=0;j<4;j++)
{
if(a[i][j]=='I') k[j][0]++;
if(a[i][j]=='O') k[j][1]++;
if(a[i][j]=='F') kk[j]++;
}
}
if(k[0][0]!=k[2][1]||k[0][1]!=k[2][0]) return 0;
if(k[1][0]!=k[3][1]||k[1][1]!=k[3][0]) return 0;
if(kk[0]!=m||kk[2]!=m) return 0;
if(kk[1]!=n||kk[3]!=n) return 0;
return 1;
}
int main()
{
while(cin>>n>>m&&n+m)
{
memset(num,0,sizeof(num));
for(int i=0;i<n*m;i++)
cin>>a[i];
if(!Pan())
{
// cout<<"hehe"<<endl;
cout<<"NO"<<endl;
continue;
}
sort(a,a+n*m);
l=1;num[0]=1;
for(int i=1;i<n*m;i++)
{
if(a[i]!=a[i-1])
{
num[l]=1;
a[l++]=a[i];
}
else
num[l-1]++;
}
if(dfs(1,1)) cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}