The New Villa -uva 隐式图搜索

没什么难得。。。拿一个结构题储存每一步的状态就行了。。。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define MAXD 10 + 5
#define MAX_SIZE 10000 + 10
int G[MAXD][MAXD];  /*房间的连通状态*/
int L[MAXD][MAXD];  /*表示i可以控制j房间的灯*/
struct State{
    int pos;         /*当前所在的房间*/
    int light[MAXD]; /*当前每个房间里面灯的状态代表开,0代表关*/
    int rote[MAX_SIZE]; /*路线*/
    int step;/*步数*/
}st[MAX_SIZE];
int r,d,s;
int front , back ;
bool Compare(State p){
    for(int i = 1; i < back ;i++)
      if(st[i].pos == p.pos && !memcmp(p.light,st[i].light,sizeof(st[i].light)))
        return false;
    return true;
}
bool Judge_ok(int pos,int light[]){
      if(pos != r)
         return false;
      for(int i = 1;i < r;i++)
        if(light[i] != 0)
          return false;

      return true;
}
void solve(){
    front = 0; back = 0;
    st[back].pos = 1;
    memset(st[back].light,0,sizeof(st[back].light));
    st[back].light[1] = 1;
    st[back].step = 0;
    back++;
    while(front < back){
         int pos = st[front].pos;
         int light[MAXD];
         int step = st[front].step;
         int rote[MAX_SIZE];
         memcpy(rote ,st[front].rote ,sizeof(st[front].rote));
         memcpy(light,st[front].light,sizeof(st[front].light));
         /*在一个房间可以有2个动作,一个是走到下一个房间,另外一个是开灯*/
         /*先考虑走路*/
         if(Judge_ok(pos,light)){
             printf("The problem can be solved in %d steps:\n",step);
             for(int i = 0 ; i < step ;i++)
                if(rote[i] <= 10)
                  printf("- Move to room %d.\n",rote[i]);
                else  if(rote[i] <30)
                  printf("- Switch on light in room %d.\n",rote[i]-15);
                else
                  printf("- Switch off light in room %d.\n",rote[i]-30);
                return ;
         }
         for(int i = 1;i <= r; i++)
             if(G[pos][i] == 1 && light[i] == 1) /*如果房间是连通的,并且房子开着灯*/{
             memcpy(st[back].light,light,sizeof(light));
             memcpy(st[back].rote,rote,sizeof(rote));
             st[back].step = step;
             st[back].pos = i;
             st[back].rote[st[back].step++] = i;
             if(Compare(st[back]))
                back++;
         }
         /*再考虑是否开灯关灯*/
         for(int i = 1;i <= r; i++)
            if(L[pos][i] && pos != i){ /*如果这个房间可以打开另一个房间的灯*/
            memcpy(st[back].light,light,sizeof(light));
            memcpy(st[back].rote,rote,sizeof(rote));
                 if(st[back].light[i] == 0) st[back].light[i] = 1;
            else if(st[back].light[i] == 1) st[back].light[i] = 0;
            st[back].pos = pos;
            st[back].step = step;
            if(st[back].light[i] == 1)
            st[back].rote[st[back].step++] = i + 15;
            else
            st[back].rote[st[back].step++] = i + 30;
            /* +15代表是开灯操作*/
            if(Compare(st[back]))
                back++;
         }
         front++;
    }
    printf("The problem cannot be solved.\n");
    return ;
}
int main(){

    int Case = 1;
    while(scanf("%d%d%d",&r,&d,&s)){
        if(!r && !d && !s)  break;
        memset(G,0,sizeof(G));
        memset(L,0,sizeof(L));
        for(int i = 0 ; i < d ; i++){
            int x,y;
            scanf("%d%d",&x,&y);
            G[x][y] = G[y][x] = 1;
        }
        for(int i = 0; i < s;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            L[x][y] = 1;
        }
        printf("Villa #%d\n",Case++);
        solve();
        printf("\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值