uva211 The Domino Effect

本文介绍了一道使用C++实现的状态空间搜索题,涉及到DFS算法。题目要求根据输入的骨牌布局,找出所有可能的排列方式。代码中详细解释了思路,包括横放和竖放骨牌的判断,并展示了AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

输出格式十分蛋疼,题目还不说清楚,难道指望我能从vj的output排版看懂输出格式?全靠uDebug。懒得弄明白了,如果你也因为格式过不去,直接抄我的吧……

思路简述

一道状态空间搜索题。用dfs从上到下一行一行地搜索,每一行从左到右dfs两种状态——横竖放置骨牌,并将骨牌编号填充至ans数组保存,直至本行没有空位,此时列数+1后==maxc,判断是搜索下一行,还是已经填充完了ans直接输出答案

AC代码

#include <iostream>
#include <cstring>
#include <iomanip>// setw()设置紧跟在后面的字段的输出宽度

//#define test

using namespace std;

const int maxr=7,maxc=8,maxb=28+1;// 最大行列数,最大牌数加一

int pips[maxr][maxc];

int ans[maxr][maxc];

bool bones[maxb][maxb];

// pips=>Bone
int id[7][7];// pips对应的牌的编号
int Bone;// 牌的编号

int cnt;

void dfs(int row,int col){
    if(col==maxc){
        // 填充完毕
        if(row==maxr-1){
            ++cnt;
            for(int i=0;i<maxr;i++){
                for(int j=0;j<maxc;j++){
                    // if(ans[i][j]<10) cout<<" ";
                    // cout<<"  "<<ans[i][j];
                    cout<<setw(4)<<ans[i][j];// 设置输出宽度,不足则前补空格
                    if(j==maxc-1) cout<<"\n";
                }
            }
            cout<<"\n\n";
        }
        // 下一行
        else{ dfs(row+1,0);}
        return;
    }

    // 若格子已被上一行的竖着的占用
    if(ans[row][col]!=0){
        // 往后找空位;若找不到,就会进入上面的col==maxc
        for(int i=col+1;i<=maxc;i++){
            if(i==maxc || ans[row][i]==0){
                dfs(row,i);
                return;
            }
        }
    }

    // 横放
    if(col+1<maxc){
        // 右边格子是否被占用,否,则检查有没有牌
        if(ans[row][col+1]==0){
            int idx1=pips[row][col],idx2=pips[row][col+1];
            if(bones[idx1][idx2]){
                bones[idx1][idx2]=false;
                bones[idx2][idx1]=false;
                ans[row][col]=id[idx1][idx2];
                ans[row][col+1]=id[idx1][idx2];
                dfs(row,col+2);
                // 回复
                bones[idx1][idx2]=true;
                bones[idx2][idx1]=true;
                ans[row][col]=0;
                ans[row][col+1]=0;
            }
        }
    }
    //竖放
    if(row+1<maxr){
        // 下方格子不可能被占用,只检查有没有牌
        int idx1=pips[row][col],idx2=pips[row+1][col];
        if(bones[idx1][idx2]){
            bones[idx1][idx2]=false;
            bones[idx2][idx1]=false;
            ans[row][col]=id[idx1][idx2];
            ans[row+1][col]=id[idx1][idx2];
            dfs(row,col+1);
            // 回复
            bones[idx1][idx2]=true;
            bones[idx2][idx1]=true;
            ans[row][col]=0;
            ans[row+1][col]=0;
        }
    }
}

void solve(){
    memset(bones,-1,sizeof(bones));// 起初,牌都有(true)
    memset(ans,0, sizeof(ans));// 未填充的标记为0
    dfs(0,0);
}

int main(){
#ifdef test
    freopen("D:\\college\\clionworkplace\\test_c++2\\in.txt","r",stdin);
    freopen("D:\\college\\clionworkplace\\test_c++2\\out.txt","w",stdout);
#endif
    int kase=1;
    bool first=true;
    // pips=>Bone
    Bone=1;
    for(int i=0;i<7;i++){
        for(int j=i;j<7;j++){
            id[i][j]=Bone;
            id[j][i]=Bone++;
        }
    }
    while (cin>>pips[0][0]){
        cnt=0;
        for(int i=0;i<maxr;i++){
            for(int j=0;j<maxc;j++){
                if(i==0 && j==0) continue;
                cin>>pips[i][j];
            }
        }
        if(!first) cout<<"\n\n\n\n\n";
        first=false;
        cout<<"Layout #"<<kase<<":\n\n\n";
        for(int i=0;i<maxr;i++){
            for(int j=0;j<maxc;j++){
                cout<<setw(4)<<pips[i][j];// 设置输出宽度,不足则前补空格
                if(j==maxc-1) cout<<"\n";
            }
        }
        cout<<"\n"<<"Maps resulting from layout #"<<kase<<" are:\n\n\n";
        solve();
        cout<<"There are "<<cnt<<" solution(s) for layout #"<<kase++<<".\n";
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值