• poj2965 The Pilots Brothers' refrigerator —— 技巧性


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


    题解:自己想到的方法是枚举搜索,结果用bfs和dfs写都超时了。网上拿别人的代码试一下只是刚好不超时的,如果自己的代码在某些方面不够优化,那超时很正常。看来这题用dfs和bfs都不是好办法。 然后又看到比较厉害的技巧:“可知翻偶数次等于没翻,即没有翻的必要,翻奇数次的结果与翻一次的结果一样“”。有了这个重要结论,那么可以具体操作了:设一个二维数组以记录每个的翻转次数。对于每个‘+’,都翻转其所在的行列(注意‘+’只翻一次),然后更新翻转次数。最后统计翻转次数为奇数的,即为实际需要翻转的。(为什么我没想到这种方法。需要仔细体会这种思维)


    代码如下:

     1 #include<stdio.h>//poj2965
     2 #include<string.h>
     3 int main()
     4 {
     5     int a[5][5],sum;
     6     char map[5][5];//map开一维已足够
     7     memset(a,0,sizeof(a));
     8     for(int i = 0; i<4; i++)
     9     {
    10         scanf("%s",map[i]);
    11         for(int j = 0; j<4; j++)
    12         {
    13             if(map[i][j]=='+')
    14             {
    15                 a[i][j]--;//‘+’在下面的步骤中翻了两次,要减少一次
    16                 for(int k = 0; k<4; k++)
    17                 {
    18                     a[k][j]++;
    19                     a[i][k]++;
    20                 }
    21             }
    22         }
    23     }
    24     sum = 0;
    25     for(int i = 0; i<4; i++)
    26     for(int j = 0; j<4; j++)
    27     {
    28         if(a[i][j]%2) sum++;
    29     }
    30     printf("%d
    ",sum);
    31 
    32     for(int i = 0; i<4; i++)
    33     for(int j = 0; j<4; j++)
    34     {
    35         if(a[i][j]%2)
    36             printf("%d %d
    ",i+1,j+1);
    37     }
    38 }
    View Code


    对了,附上自己wa了的dfs和bfs;

    dfs:

     1 #include<cstdio>//poj 2965dfs 超时未过
     2 #include<cstring>
     3 #define MIN(a,b) (a<b?a:b)
     4 
     5 int a[20],ans[20];
     6 
     7 int get()
     8 {
     9     for(int i = 0; i<16; i++)
    10         if(a[i]) return 0;
    11     return 1;
    12 }
    13 
    14 void flip(int loc)
    15 {
    16     int x = loc/4, y = loc%4;
    17     a[loc] = !a[loc];
    18     for(int k = 0; k<4; k++)
    19         a[x*4+k] = !a[x*4+k];
    20     for(int k = 0; k<4; k++)
    21         a[k*4+y] = !a[k*4+y];
    22 }
    23 
    24 int dfs(int loc,int step,int tar)
    25 {
    26     if(loc>16) return 0;
    27 
    28     if(step==tar && get())
    29        return 1;
    30 
    31     else
    32     {
    33         flip(loc);
    34         ans[step] = loc;
    35         if(dfs(loc+1,step+1,tar)) return 1;
    36         flip(loc);
    37 
    38         if(dfs(loc+1,step,tar)) return 1;
    39 
    40     }
    41     return 0;
    42 }
    43 
    44 int main()
    45 {
    46     int t;
    47     char s[10];
    48 
    49     memset(ans,-1,sizeof(ans));
    50     for(int i = 0; i<4; i++)
    51     {
    52         scanf("%s",s);
    53         for(int j = 0; j<4; j++)
    54         {
    55             if(s[j]=='+') a[i*4+j] = 1;
    56             else a[i*4+j] = 0;
    57         }
    58     }
    59     int i;
    60     for(i = 1; i<=16; i++)
    61     {
    62         if(dfs(0,0,i)) break;
    63     }
    64     printf("%d
    ",i);
    65     for(int k = 0; k<i; k++)
    66     {
    67         if(ans[k]!=-1)
    68             printf("%d %d
    ",ans[k]/4+1, ans[k]%4+1);
    69     }
    70 
    71     return 0;
    72 }
    View Code

    bfs:(bfs的队列可能不够大,溢出。用stl的话又怎么记录路径呢?)

     1 #include<cstdio>//poj 2965 bfs 未过
     2 #include<cstring>
     3 #include<queue>
     4 
     5 using namespace std;
     6 
     7 int ss,vis[65536],pre[65536];
     8 struct node
     9 {
    10     int status, step,loc;
    11 };
    12 node q[65536];
    13 
    14 void calcul( node *next,int i)
    15 {
    16     if(next->status&(1<<i)) next->status -= (1<<i);
    17     else  next->status += (1<<i);
    18 }
    19 
    20 void turn (node *next,int i)
    21 {
    22     calcul(next,i);
    23     int xi = i/4, yi = i%4;
    24     for(int k = 0; k<4; k++)
    25         calcul(next,xi*4+k);
    26     for(int k = 0; k<4; k++)
    27         calcul(next,k*4+yi);
    28 }
    29 
    30 int bfs()
    31 {
    32     int front = 0, rear = 1;
    33     q[front].status = ss, q[front].step = 0;
    34     vis[q[front].status] = 1;
    35     if(q[front].status==0)
    36         return front;
    37     memset(vis,0,sizeof(vis));
    38     memset(pre,0,sizeof(pre));
    39     while(front<rear)
    40     {
    41         for(int i = 0; i<16; i++)
    42         {
    43             q[rear].status = q[front].status;
    44             turn(&q[rear],i);
    45             if(vis[q[rear].status]) continue;
    46 
    47             q[rear].loc = i;
    48             q[rear].step = q[front].step + 1;
    49             pre[rear] = front;
    50             vis[q[rear].status] = 1;
    51 
    52             if(q[rear].status==0) return rear;
    53             rear++;
    54         }
    55         front++;
    56     }
    57     return -1;
    58 }
    59 
    60 void pri_path(int rear)
    61 {
    62     if(q[rear].step>1) pri_path(pre[rear]);
    63     printf("%d %d
    ",q[rear].loc/4+1, q[rear].loc%4+1);
    64 }
    65 
    66 int main()
    67 {
    68     int t;
    69     char s[10];
    70     ss = 0;
    71 
    72     for(int i = 0; i<4; i++)
    73     {
    74         scanf("%s",s);
    75         for(int j = 0; j<4; j++)
    76         {
    77             if(s[j]=='+') ss += 1<<(i*4+j);
    78         }
    79     }
    80     int rear = bfs();
    81     printf("%d
    ",q[rear].step);
    82 
    83     pri_path(rear);
    84     return 0;
    85 }
    View Code
  • 相关阅读:
    2017.04.05-2017.07.14封闭开发总结
    Android读取Manifest文件下Application等节点下的metadata自定义数据
    MyEclipse Hibernate Reverse Engineering 找不到项目错误
    web服务器决定支持多少人同时在线的因素
    配置servers时,错误:Setting property 'source' to 'org.eclipse.jst.jee.server:hczm' did not find a matching property
    查看端口被占用
    高德开发 android 出现 key 鉴权失败
    Android EventBus
    javascript 中的数据驱动页面模式
    读书笔记之
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/7538786.html
Copyright © 2020-2023  润新知