POJ2965 状态压缩+BFS,DFS枚举,以及大牛的解法~

POJ2965 状态压缩+BFS,DFS枚举,以及大牛的解法~

和poj1753非常相似,这题用状态压缩+BFS同样可以解,状态压缩就是用二进制来表示一种状态。

这是我在1753上改的BFS+状态压缩代码:

 

//二进制+BFS写法
#include<iostream>
using namespace std;   //解决问题路径搜索

bool flag[65536];
int step[65536];
struct con
{
    int f;
    int k;
}connect[65536];
int ans[65536];
int qstate[65536];  //搜索状态
int top=0;
int rear=0;
void Init()
{
    int temp=0;
    char c;
    for(int i=0; i < 4; i++)
         for(int j = 0; j < 4; j++)
         {
             cin>>c;
             if('+' == c)
                 temp |= (1<<(i*4+j));
         }
    qstate[rear++] = temp;
     flag[temp]  = true;
}

int move(int state,int i)
{
    int temp=0;
    temp |= (1<<i);     //翻自己
    int j;
    for(j=i;(j+1)%4!=0;j++)//右
    temp |= (1<<(j+1));
    for(j=i;(j)%4!=0;j--)//左
    temp |= (1<<(j-1));
    for(j=i;(j-4)>=0;j=j-4)//上
    temp |= (1<<(j-4));
    for(j=i;(j+4)<16;j=j+4)//下
    temp |= (1<<(j+4));

    return (state ^ temp);
}

bool BFS()
 {
     while(rear > top)
     {
         int state = qstate[top++];
         for(int i=0; i < 16; i++)
         {
             int temp;
             temp = move(state,i);
             if(0 == state)
             {
                 cout<<step[state]<<endl;
                 int x=0;
                 for(int j=step[state]-1;j>=0;j--)
                 {
                     ans[j]=connect[x].k;
                     x=connect[x].f;
                 }
                 for(int j=0;j<step[state];j++)
                 {
                     cout<<(ans[j]/4)+1<<' '<<(ans[j]%4)+1<<endl;
                 }
                 return true;
             }
             else if(!flag[temp]) //防止重复搜索
             {
                 qstate[rear++] = temp;
                 flag[temp] = true;
                 step[temp] = step[state]+1;
                 connect[temp].f=state;
                 connect[temp].k=i;
             }
         }
     }

     return false;
 }
 int main(void)
 {
     Init();
     BFS();
     return 0;
 }

然后是参考网上DFS枚举的方法,以后将继续对DFS枚举进行理解。代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 10;
struct node
{
    int p, q;
}a[18];
int map[N][N], ans, flag;
void Change(int x, int y) //翻转函数
{
    int i;
    map[x][y] = !map[x][y];
    for (i = 1; i <= 4; ++i)
    {
        map[x][i] = !map[x][i];
        map[i][y] = !map[i][y];
    }
}
int Judge() //判断函数
{
    int i, j;
    for (i = 1; i <= 4; ++i)
    {
        for (j = 1; j <= 4; ++j)
        {
            if (map[i][j] == 0)
            {
                return 0;
            }
        }
    }
    return 1;
}
void DFS(int x, int y, int step)
{
    if (step == ans)
    {
        flag = Judge();//不能加if(flag),否则超时
        return ;
    }
    if (flag || x >= 5)
    {
        return ;
    }
    Change(x, y);
    if (y < 4)
    {
        DFS(x, y + 1, step + 1);
        a[step].p = x;
        a[step].q = y;
    }
    else                                //全部16枚举一遍
    {
        DFS(x + 1, 1, step + 1);
        a[step].p = x;
        a[step].q = y;
    }
    Change(x, y);                       //再原路返还
    if (y < 4)
    {
        DFS(x, y + 1, step);
    }
    else
    {
        DFS(x + 1, 1, step);
    }
}
int main()
{
    int i, j;
    char str;
    for (i = 1; i <= 4; ++i)
    {
        for (j = 1; j <= 4; ++j)
        {
            scanf("%c", &str);
            if (str == '-')
            {
                map[i][j] = 1;
            }
            else
            {
                map[i][j] = 0;
            }
        }
        getchar();//度掉回车
    }
    flag = 0;
    for (i = 0; i <= 16; ++i)
    {
        ans = i;
        DFS(1, 1, 0);
        if (flag)
        {
            break;
        }
    }
    if (flag)
    {
        printf("%d\n", ans);
        for (i = 0; i < ans; ++i)
        {
            printf("%d %d\n", a[i].p, a[i].q);
        }
    }
    return 0;
}

 

 

 

再最后就是网上大神的算法,找到其中巧妙的规律。这也提醒我以后多将过程展示出来可从中发现重要的信息!:

/*既然说要把所有的开关变成是打开的话,那么怎么样才能做而且又不影响其他的布局呢?如果没遇到一个‘+’即关闭的开关,我们就把这个开关所在行和列包括它本身(本身只操作一次)都操作一次的话。那么可以计算它本身的状态变化次数为7,其同在一行和一列的元素则状态变化为4,余下的状态转化都是2.可以得到这个方法可以在不影响其它元素的状态下将关闭的开关打开(因为偶数次对状态实际上是没有影响的)。所有我们只要遇到一个'+'就重复上面的操作,而且用一个数组记录下每个元素被操作的次数。最后扫描一次数组,操作次数为奇数的就是我们需要操作的点(偶数次操作相当于没有操作)。
代码:*/
#include<stdio.h>
long m[5][5] ;
void dose(int x,int y){//没操作一次就对元素标记数组加一
for(int i = 1;i<=4;i++){
m[x][i]++ ;
if(i!=x)m[i][y]++ ;
}
}
int steps(){//计算需要操作的次数
int c = 0 ;
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
if(m[i][j]%2) c++ ;
return c ;
}
int main()
{
int
char c ;
for(i = 1 ; i <= 4 ; i++){
for(j = 1 ; j <= 4 ; j++){
scanf("%c",&c) ;
if(c=='+') dose(i,j) ;
}
getchar() ;
}
printf("%d\n",steps()) ;
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
if(m[i][j]%2)//遇到是奇数的就打印出来
printf("%d %d\n",i,j) ;
return 0 ;
}

 

当然还有一种纯纯的暴力枚举也能过。。用16个for语句的枚举。。

 

转载于:https://www.cnblogs.com/amourjun/archive/2013/03/15/5134220.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/110191.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JRebel 热部署插件的安装使用

    JRebel 热部署插件的安装使用文章目录Jrebel简介JRebel的安装和使用idea安装JRebelJRebel的使用JRebel的激活Jrebel简介  当你修改doGet,doPost等一些内容时,你再次访问,访问到的内容不变,除非重启或重新加载class文件。  用Jrebel可快速实现热部署,节省了大量重启时间,提高了个人开发效率。JRebel的安装和使用idea安装JRebelNew->settings->plugins->Marketplace搜索插件jrebel进行安装或

    2022年5月22日
    36
  • 为Nginx开启SSI模块以支持SHTML解析

    为Nginx开启SSI模块以支持SHTML解析

    2021年8月29日
    56
  • opencv的sift_opencv sift

    opencv的sift_opencv sift《SIFT原理与源码分析》系列文章索引:http://blog.csdn.net/xiaowei_cqu/article/details/8069548尺度空间理论自然界中的物体随着观测尺度不同有不同的表现形态。例如我们形容建筑物用“米”,观测分子、原子等用“纳米”。更形象的例子比如Google地图,滑动鼠标轮可以改变观测地图的尺度,看到的地图绘制也不同;还有电影中的拉伸镜头等等…

    2022年10月15日
    2
  • kworkers_kworker进程

    kworkers_kworker进程名字的意思什么时候有的这么看系统中查看显示的内容怎么看有什么用参考名字的意思KernelWorker什么时候有的kworker是3.x内核引入的这么看系统中查看Linux下使用ps-ef|grepkowrker显示的内容怎么看显示的格式kworker/%u:%d%su:是unbound的缩写,代表没有绑定特定的CPU,kworker/u2:0中的2是work_pool的

    2022年9月24日
    4
  • Hashtable 和 HashMap 的区别

    Hashtable 和 HashMap 的区别Hashtable和HashMap的区别

    2025年11月24日
    3
  • 看了这篇文章觉得MySQL读写分离这么简单「建议收藏」

    点赞多大胆,就有多大产!有支持才有动力!微信搜索公众号【达摩克利斯之笔】获取更多资源,文末有二维码!前言​  Mysql优化那篇文章有朋友留言说就这么点?,深深刺痛了晓添的心,感觉知识深度被小看了,痛定思痛决定发布读写分离,分表分库优化文章,其实这系列文章也在Mysql优化的计划之内,最近较忙断断续续写的有点难受,到今天才跟大家见面,篇幅有限这篇我们来说说基于Mycat实现读写分离,话不多…

    2022年4月13日
    59

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号