ZOJ1002解题报告

回溯算法——入门

题目如下:

ZOJ1002

题目大意

在一个最大为4*4的方格内建blockhouse(
碉堡)
但是有条件
1. 两个及以上blockhouse不能位于同一行或者同一列
2. 如果有wall,两个blockhouse可以位于其两侧
3. blockhouse只能建在空地
注意的点
1. 多次输入;输入0时,结束


思路:

这里写图片描述
按上图顺序进行dfs,按下面代码进行k与map[x][y]中的x和y的转换

if(k%n == 0) {
        x=(k-1)/n;
        y=n-1;
    }
    else{
         y = k%n-1;
         x = k/n;
    } 

AC——C++代码:

比较low,>_<
有一些输出的注释,自己调试使用的

#include"cstdio"
#include "iostream"

using namespace std;


int best ;
char map[4][4];
int n;


bool judge(int x, int y){
    bool a=true,b=true,c=true;
    for(int i=x-1;i>=0;i--){
        //printf("%c\n",map[i][y]);
        if(map[i][y] == 'O') {b = false;break;}
        if(map[i][y] == 'X') {b = true;break;}
    }
    for(int i=y-1;i>=0;i--){
    //  printf("%c\n",map[x][i]);
        if(map[x][i] == 'O') {a = false;break;}
        if(map[x][i] == 'X') {a = true; break;}
    }
    //cout<<a<<b<<endl;
    c = a&&b;
    return c;
}
 void backtrack(int k, int count){
    //printf("k:%d count:%d\n",k,count);
    int x,y;
    if(k >n*n){
        if(count > best)
            best = count;
        return ;
    }

    if(k%n == 0) {
        x=(k-1)/n;
        y=n-1;
    }
    else{
         y = k%n-1;
         x = k/n;
    } 
    //printf("x:%d y:%d\n",x,y);
    if(map[x][y] == '.' && judge(x, y)){
    //  printf("%c\n",map[x][y]);
        map[x][y] = 'O';
        backtrack(k+1, count+1);
        map[x][y] = '.';
    }

    backtrack(k+1, count);
 }

int main(){

    char ch;
    while(scanf("%d",&n)&&n!=0){
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++){
                map[i][j] = '.';    
            }
        //二维字符数组
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
            cin>>ch;
            map[i][j] = ch; 
            }
        }

        //计算
        best = 0;
        backtrack(1, 0);
        printf("%d\n", best);
    }
    return 0;
}




/*自己程序出问题的例子
3
...
..X
.X.
3
...
..X
.XX 
*/
总结:

其实对于这道题,自己之前的一个小错误,我调试了好久,我思考了一下,归根到底还是因为自己对回溯算法的不熟悉。
然后自己又尝试另一种方法去再次看回溯算法,发现其实它就是dfs的思想,然后也是按树的先根顺序进行搜索,需要自己发现的就是:进入左子树搜索时的条件,进入右子树搜索的条件,以及一些减枝的条件。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值