POJ2965 The Pilots Brothers' refrigerator ACM解题报告 (递归+深搜)


啦啦啦,我是萌萌哒的初学者,刚接触代码不久,写的比较难看,只是为了便于自己回忆复习。本题是POJ2965,一道搜索题,方法比较多,但是我只会用递归搜索,题意是要把每次操作一个handle,然后一整行一整列的handle都会反过来,要求是得到4*4的矩阵中都为-时冰箱打开。翻转奇数次等同于翻转1次,翻转偶数次等同于没有翻转,so只要考虑每块翻转一次的情况,暴力搜索翻转1块到16块的情况。
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int result[20],last,b[20],c[20],flag=0;
bool all(int arr[])
{
    for(int i=0;i<16;i++)
    {
        if(arr[i]!=0)
            return false;
    }
    return true;
}
void fan(int arr[],int i)
{
    int x=i/4;
    int y=i%4;
    arr[i]=!(arr[i]);
    for(int j=1;j<4;j++)
    {
        if(x-j>=0) arr[i-4*j]=!(arr[i-4*j]);
        if(x+j<=3) arr[i+4*j]=!(arr[i+4*j]);
        if(y-j>=0) arr[i-j]=!(arr[i-j]);
        if(y+j<=3) arr[i+j]=!(arr[i+j]);
    }
}
void solve(int len,int count,int num)
{
    for(int i=len;i>=count;i--)
    {
        result[count-1]=i-1;
        if(count==1)
        {
            for(int j=0;j<16;j++)
                c[j]=b[j];
            for(int j=num-1;j>=0;j--)
                fan(c,result[j]);
            if(all(c))
            {
                last=num;
                flag=1;
                break;
            }
        }
        else
        {
            solve(i-1,count-1,num);
            if(flag)
                break;
        }
    }
}
int main()
{
    char a[5][5];
    memset(b,0,sizeof(b));
    memset(result,0,sizeof(result));
    for(int i=0;i<4;i++)
    {
        scanf("%s",a[i]);
        for(int j=0;j<4;j++)
            if(a[i][j]=='+') b[i*4+j]=1;
    }
    //for(int i=0;i<16;i++)printf("%d ",b[i]);
    if(all(b))
    {
        printf("0\n");
        return 0;
    }
    last=0;
    for(int i=1;i<=16;i++)
    {
        solve(16,i,i);
        if(last==i)
        {
            printf("%d\n",last);
            for(int k=0;k<last;k++)
                printf("%d %d\n",result[k]/4+1,result[k]%4+1);
            break;
        }
    }
    return 0;
}

你可能感兴趣的:(poj)