题目链接:https://www.luogu.org/problemnew/show/P1312
(这道题debug了5天的我简直弱爆了。。。)
首先这道题可以说是十分典型的爆搜题,范围非常小,搜索的思路也比较好想,即枚举每一个点向两个方向走的不同情况,超过了规定了的步数就回溯。
这样的搜索可以得到60或者70分,如果开O2的话就可以A掉了,当然也可以搞一下玄学剪枝(例如用map记录图,在搜的时候如果搜到过的话就剪掉等),由于时间比较紧所以也就没去剪枝。
然后还要注意题目给的优先级,按照这个来搜。
最后就是这个题要把细节处理好,具体看代码吧。
code:
#include
#include
using namespace std;
int n, maps[5][8], d[2]={1, -1}, ans1[6], ans2[6], ans3[6];
bool color[5][8], suc;
bool check() {
int i, j;
for (i=0; i<5; i++)
for (j=0; j<7; j++)
if (maps[i][j]) return false;
return true;
}
void update() {
int i, j;
for (i=0; i<5; i++) {
for (j=0; j<7; j++) {
if (j==0 || maps[i][j]==0) continue;
if (maps[i][j-1]==0) {
int temp=j-1;
if (temp-1>=0) {
while (maps[i][temp-1]==0) {
temp--;
if (temp-1<0) break;
}
}
maps[i][temp]=maps[i][j];
maps[i][j]=0;
}
}
}
return ;
}
void ex(int x1, int y1, int x2, int y2) {
int temp=maps[x1][y1];
maps[x1][y1]=maps[x2][y2];
maps[x2][y2]=temp;
return ;
}
void clear() {
int i, j;
for (i=0; i<5; i++) {
for (j=0; j<7; j++) {
if (maps[i][j]==0) break;
if (color[i][j]) maps[i][j]=0;
}
}
update();
return ;
}
void mark(int x, int r, int l, int flags) {
int i;
if (flags==0) for (i=l; i<=r; i++) color[x][i]=true;
else for (i=l; i<=r; i++) color[i][x]=true;
return ;
}
bool find_clear() {
bool flag=false;
memset(color, false, sizeof(color));
int i, j, last, cnt;
for (i=0; i<5; i++) {
cnt=1, last=-1;
for (j=0; j<7; j++) {
if (maps[i][j]==last) cnt++;
else {
if (cnt>=3) {
flag=true;
mark(i, j-1, j-cnt, 0);
}
cnt=1;
}
last=maps[i][j];
if (maps[i][j]==0) break;
}
}
for (j=0; j<7; j++) {
cnt=1, last=-1;
for (i=0; i<5; i++) {
if (maps[i][j]==0) {
last=maps[i][j];
continue;
}
if (maps[i][j]==last) {
cnt++;
if (cnt>=3) {
if (i+1<5) {
if (maps[i+1][j]!=maps[i][j]) {
mark(j, i, i-cnt+1, 1);
flag=true;
}
}
else {
mark(j, i, i-cnt+1, 1);
flag=true;
}
}
}
else cnt=1;
last=maps[i][j];
}
}
if (flag) clear();
return flag;
}
void dfs(int pos) {
if (pos>n) return ;
int i, j, k, temp[5][7];
for (i=0; i<5; i++)
for (j=0; j<7; j++)
temp[i][j]=maps[i][j];
for (i=0; i<5; i++) {
for (j=0; j<7; j++) {
if (maps[i][j]==0) break;
for (k=0; k<2; k++) {
int di=i+d[k];
if (di<0 || di>=5) continue;
if (maps[di][j]==0) {
maps[di][j]=maps[i][j];
maps[i][j]=0;
}
else ex(i, j, di, j);
update();
while (find_clear());
ans1[pos]=i, ans2[pos]=j, ans3[pos]=d[k];
if (pos==n && check()) {
suc=true;
return ;
}
dfs(pos+1);
if (suc) return ;
ans1[pos]=0, ans2[pos]=0, ans3[pos]=0;
for (int is=0; is<5; is++)
for (int js=0; js<7; js++)
maps[is][js]=temp[is][js];
}
}
}
return ;
}
int main() {
int i, j, x;
cin >> n;
for (i=0; i<5; i++) {
for (j=0; j<8; j++) {
cin >> x;
maps[i][j]=x;
if (x==0) break;
}
}
dfs(1);
if (!suc) {
cout << "-1";
return 0;
}
for (i=1; i<=n; i++)
cout << ans1[i] << " " << ans2[i] << " " << ans3[i] << endl;
return 0;
}
练习爆搜和代码能力都不错的题目。