一道考数据结构的好题
要利用好斜坐标系来表示各点,原理网上都有
自己闲着无聊用冗杂的代码压时间,居然压到32ms
#include <iostream>
#include <algorithm>
using namespace std;
#define CHOICE_R 0
#define CHOICE_C 1
int side_len, triangle_num, triangle[15],
data_map[55][55][2]; //0 正 1 倒
int col_num[55][2];
bool isOK, num_map[26];
bool cmp(const int &a, const int &b)
{
return a<b;
}
int DFS_ROW(int row, int col, int choice)
{
int i, j, lenth, k, s, last_lenth;
bool ok ;
switch (choice)
{
case CHOICE_R:
for (; col <= col_num[row][1]; col++)
{
if (data_map[row][col][0])
{
break;
}
}
if (col > col_num[row][1])
{
return DFS_ROW(row, col_num[row][0], CHOICE_C);
}
last_lenth = col;
for (i = 0; i< triangle_num; i++)
{
lenth = triangle[i];
if (row+lenth > 2*side_len || col+lenth-1 > col_num[row][1])
{
return 0;
}
for (k = last_lenth; k < col+lenth; k++)
{
if (!data_map[row][k][0]) //已被填充
{
return 0; //失败
}
}
last_lenth = k;
for (j = row; j< row+lenth; j++)
{
for (k = col; k < col+lenth-j+row; k++)
{
data_map[j][k][0] = 0;
if (k != col)
{
data_map[j][k][1] = 0;
}
}
}//寻找下个点
ok = 1;
for (j = col+lenth; j<= col_num[row][1]; j++)
{
if (data_map[row][j][0])
{
if (DFS_ROW(row, j, CHOICE_R))
{
return 1;
}
else
{
ok = 0;
}
break;
}
}
if (j > col_num[row][1])
{
if (!DFS_ROW(row, col_num[row][0], CHOICE_C))
ok = 0;
else
return 1;
}
//恢复点
if (!ok)
{
for (s = row; s< row+lenth; s++)
{
for (k = col; k < col+lenth-s+row; k++)
{
data_map[s][k][0] = 1;
if (k != col)
{
data_map[s][k][1] = 1;
}
}
}
}
}
break;
case CHOICE_C:
for (; col <= col_num[row][1]; col++)
{
if (data_map[row][col][1])
{
break;
}
}
if (col > col_num[row][1])
{
if (row == 2*side_len-1) //搜索完毕
return 1;
else
return DFS_ROW(row+1, col_num[row][0], CHOICE_R);
}
for (i = 0; i< triangle_num; i++)
{
lenth = triangle[i];
if (row+lenth > 2*side_len || col > col_num[row+lenth-1][1] || col-lenth+1 < col_num[row+lenth-1][0])
{
return 0;
}
for (j = row, k = col; j< row+lenth && k > col-lenth; j++, k--)
{
if (!data_map[j][col][1] || !data_map[j][k][1])
{
return 0;
}
}
for (j = row; j< row+lenth; j++)
{
for (k = col-j+row; k <= col ; k++)
{
data_map[j][k][1] = 0;
if (k != col)
{
data_map[j][k][0] = 0;
}
}
}//寻找下个点
ok = 1;
for (j = col+1; j<= col_num[row][1]; j++)
{
if (data_map[row][j][1])
{
if (DFS_ROW(row, j, CHOICE_C))
{
return 1;
}
else
{
ok = 0;
}
break;
}
}
if (j > col_num[row][1])
{
if (row == 2*side_len-1)
return 1;
if (!DFS_ROW(row+1, col_num[row+1][0], CHOICE_R))
ok = 0;
else
return 1;
}
//恢复点
if (!ok)
{
for (j = row; j< row+lenth; j++)
{
for (k = col-j+row; k <= col ; k++)
{
data_map[j][k][1] = 1;
if (k != col)
{
data_map[j][k][0] = 1;
}
}
}
}
}
break;
}
return 0;
}
inline void solve()
{
memset(data_map, 0, sizeof(data_map));
int i, j;
for (i = 0; i<= side_len; i++)
{
for (j = side_len - i; j <= side_len*2; j++)
{
data_map[i][j][0] = data_map[i][j][1] = 1;
if (j == side_len*2)
{
data_map[i][j][0] = 0;
}
}
col_num[i][0] = side_len - i;
col_num[i][1] = side_len*2;
}
for (i = side_len; i< 2*side_len; i++)
{
for (j = 0; j < 3*side_len-i; j++)
{
data_map[i][j][0] = data_map[i][j][1] = 1;
if ( j == 0 )
{
data_map[i][j][1] = 0;
}
}
col_num[i][0] = 0;
col_num[i][1] = 3*side_len-i-1;
}
data_map[side_len][2*side_len][1] = 0;
if (DFS_ROW(0, side_len, CHOICE_R))
{
isOK = 1;
}
}
int main()
{
int sum, i, j, k, tmp_triangle[15];
cin>>sum;
while (sum--)
{
cin>>side_len>>triangle_num;
isOK = 0;
k = 0;
memset(num_map, 0, sizeof(num_map));
for (i = 0; i< triangle_num; i++)
{
cin>>tmp_triangle[i];
if (side_len % tmp_triangle[i] == 0)
{
isOK = 1;
goto my_stop;
}
if (tmp_triangle[i] > side_len)
{
isOK = 0;
goto my_stop;
}
if (!num_map[tmp_triangle[i]])
{
triangle[k++] = tmp_triangle[i];
for (j = tmp_triangle[i]; j < 26; j += tmp_triangle[i])
{
num_map[j] = 1;
}
}
}
triangle_num = k;
sort(triangle, triangle+triangle_num, cmp);
solve();
my_stop:
if (isOK)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
return 0;
}