《算法竞赛进阶指南》. 涂满它!搜索IDA*

该博客介绍了一个使用IDA*算法解决连通块问题的C++实现。通过记录和更改连通块周围的颜色,递归进行深度优先搜索(DFS),并以剩余颜色数量作为估值函数。程序读取9x9的矩阵输入,输出达到目标状态所需的最小操作次数。

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

在这里插入图片描述

IDA*算法,使用连通块之外剩下的颜色个数作为估值函数。每次记录连通块周围颜色,然后改成这个颜色,dfs下去即可。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 9;
typedef pair<int,int>pii;
#define x first
#define y second
int s[N][N],n;
bool st[N];
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
inline int f(){
    int cnt=0;
    memset(st,0,sizeof st);
    for(register short i=0;i<n;i++)
    for(register short j=0;j<n;j++)
    if(!st[s[i][j]])st[s[i][j]]=1,cnt++;
    return cnt-1;
}
inline void DFS(bool vis[N][N],int x,int y){
    vis[x][y]=1;
    for(register short i=0;i<4;i++){
        int a=x+dx[i],b=y+dy[i];
        if(a<0||a>=n||b<0||b>=n)continue;
        if(vis[a][b])continue;
        if(s[a][b]!=s[0][0])continue;
        DFS(vis,a,b);
    }
}
inline void operate(bool vis[N][N],int u){
      for(register short i=0;i<n;i++)
      for(register short j=0;j<n;j++)
      if(vis[i][j])s[i][j]=u;
}
inline bool dfs(int u,int depth,int last){
    int res=f();
    if(u+res>depth)return false;
    if(!res)return true;
     bool cor[6],vis[N][N];
    memset(vis,0,sizeof vis);
    memset(cor,0,sizeof cor);
    DFS(vis,0,0);
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    if(vis[i][j])
    {
        for(register short k=0;k<4;k++)
        {
            int x=i+dx[k],y=j+dy[k];
            if(x<0||x>=n||y<0||y>=n)continue;
            if(vis[x][y])continue;
            cor[s[x][y]]=1;
        }    
    }
     int bk[N][N];
    memcpy(bk,s,sizeof s);
    for(register short i=0;i<6;i++)
    {
        if(cor[i]&&i!=last){
            operate(vis,i);
            if(dfs(u+1,depth,i))return true;
            memcpy(s,bk,sizeof bk);
        }
    }
    return false;
}
int main(){
  while(scanf("%d",&n),n){
      for(register short i=0;i<n;i++)
      for(register short j=0;j<n;j++)
      scanf("%d",&s[i][j]);
    int depth(0);
    while(!dfs(0,depth,s[0][0]))depth++;
    printf("%d\n",depth);
  }
    return 0;    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值