学习随笔——POJ题目2965:The Pilots Brothers' refrigerator解答

本题题目链接:http://poj.org/problem?id=2965

本题前置题目:POJ1753  相关讲解链接:https://www.cnblogs.com/johnsonstar/p/15981589.html

题目截图如下:

思路依然和POJ1753一样是枚举,区别如下:①最终判定条件为所有字符全为“-” ②需要记录经过的点的坐标

关于坐标的记录,本处思路是开辟一个栈和一个最终输出数组来记录坐标。当棋子第一次被翻转,便将坐标压入栈中;当棋子二次翻转(也即复位)后,我们再将坐标弹出。每当最小步数更新时,我们便将临时坐标填入最终输出实现更新。

代码如下:

 1 #include <stdio.h>
 2 #include <iostream>
 3 using namespace std; 
 4 typedef struct M_Stack{
 5     int x_pos[30];
 6     int y_pos[30];
 7     int num;
 8 }M_Stack;
 9 M_Stack pos_ans; 
10 int mem[16]={0};//记忆化
11 int ans=100;//最终解答
12 int x_ans[30]={0};
13 int y_ans[30]={0};//x坐标与y坐标最终输出
14 int Stack_num=0;
15 void Stack_In (int x,int y){
16     x_ans[Stack_num]=x;
17     y_ans[Stack_num]=y;
18     Stack_num++;
19 }//将栈元素压入 
20 void Stack_Out (){
21     Stack_num--;
22     x_ans[Stack_num]=0;
23     y_ans[Stack_num]=0;
24 }//将栈元素弹出 
25 void Stack_change (){
26     for (int i=0;i<Stack_num;i++){
27         pos_ans.x_pos[i]=x_ans[i];
28         pos_ans.y_pos[i]=y_ans[i];
29     }
30     pos_ans.num=Stack_num;
31 }//更新栈元素 
32 int find_x (int i){
33     return i/4+1;
34 }//坐标转换 
35 int find_y (int i){
36     return i%4+1;
37 }//坐标转换 
38 void change (int i){
39     int x_pos=i/4;
40     int y_pos=i%4;
41     mem[i % 16] =! mem[i % 16];
42     mem[(i + 4) % 16] = !mem[(i + 4) % 16];
43     mem[(i + 8) % 16] = !mem[(i + 8) % 16];
44     mem[(i + 12) % 16] = !mem[(i + 12) % 16];
45     mem[x_pos * 4 + y_pos % 4] = !mem[x_pos * 4 + y_pos % 4];
46     mem[x_pos * 4 + (y_pos + 1) % 4] = !mem[x_pos * 4 + (y_pos + 1) % 4];
47     mem[x_pos * 4 + (y_pos + 2) % 4] = !mem[x_pos * 4 + (y_pos + 2) % 4];
48     mem[x_pos * 4 + (y_pos + 3) % 4] = !mem[x_pos * 4 + (y_pos + 3) % 4];
49     mem[i] = !mem[i];
50 }//翻转 
51 bool Judge (){
52     for (int i=0;i<16;i++){
53             if (mem[i]!=1)
54                 return false;
55         }
56     return true;
57 }//判断是否满足终止条件 
58 void Enum (int num,int count){
59     if (Judge()){
60         if (count<ans){
61             ans=count;
62             Stack_change();//更新 
63             return ;
64         }
65     }
66     if (num>=16)
67         return ;
68     int x_pos=find_x(num);
69     int y_pos=find_y(num);
70     change(num);
71     Stack_In (x_pos,y_pos);//第一次翻转将坐标压入 
72     Enum (num+1,count+1);
73     change(num);
74     Stack_Out();//复位将坐标弹出 
75     Enum (num+1,count);
76     return ;
77 }
78 int main (int argc,char* argv[]){
79     char temp;
80     for (int i=0;i<16;i++){
81         cin>>temp;
82         if (temp=='-')
83             mem[i]=1;
84     }
85     Enum(0,0);
86     printf("%d\n",ans);
87     for (int i=0;i<pos_ans.num;i++)
88         printf("%d %d\n",pos_ans.x_pos[i],pos_ans.y_pos[i]);
89     return 0;
90 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值