POJ2965高消+搜索

The Pilots Brothers' refrigerator

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 12909   Accepted: 4833   Special Judge

Description

The game “The Pilots Brothers: following the stripy elephant” has a quest where a player needs to open a refrigerator.

There are 16 handles on the refrigerator door. Every handle can be in one of two states: open or closed. The refrigerator is open only when all handles are open. The handles are represented as a matrix 4х4. You can change the state of a handle in any location [i,
j]
 (1 ≤ i, j ≤ 4). However, this also changes states of all handles in row i and all handles in column j.

The task is to determine the minimum number of handle switching necessary to open the refrigerator.

Input

The input contains four lines. Each of the four lines contains four characters describing the initial state of appropriate handles. A symbol “+” means that the handle is in closed state, whereas the symbol “−” means “open”. At least one of the handles is
initially closed.

Output

The first line of the input contains N – the minimum number of switching. The rest N lines describe switching sequence. Each of the lines contains a row number and a column number of the matrix separated by one or more spaces. If there are several solutions,
you may give any one of them.

Sample Input

-+--
----
----
-+--

Sample Output

6
1 1
1 3
1 4
4 1
4 3
4 4

Source

Northeastern Europe 2004, Western Subregion

 

题解:

高斯消元入门请看POJ1222 点击打开链接POJ1222

这题与之前的题目有所不同 不仅仅求最小步数 而且要输出先后顺序

实际上还是有无穷解要DFS的 所以当DFS出最少解的时候

数组X[i]里记录的值就是方程组的解

通过之前将二维坐标转换为方程组的系数阵的方法 现在知道是第几个的解

在将这个值转化为坐标即可

 

#include <iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=230;
int a[maxn][maxn+1],x[maxn];//a 是系数矩阵和增广矩阵,x 是最后存放的解
// a[][maxn]中存放的是方程右面的值(bi)
int equ,var;//equ 是系数阵的行数,var 是系数矩阵的列数(变量的个数)
int free_num,ans=100000000;

int abs1(int num) //取绝对值
{
    if (num>=0) return num;
    else
        return -1*num;
}
void Debug(void)
{
    int i, j;
    for (i = 0; i < equ; i++)
    {
        for (j = 0; j < var + 1; j++)
        {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;
}
//调试输出,看消元后的矩阵值,提交时,就不用了
inline int gcd(int a, int b) //最大公约数
{
    int t;
    while (b != 0)
    {
        t = b;
        b = a % b;
        a = t;
    }
    return a;
}

inline int lcm(int a, int b) //最小公倍数
{
    return a * b / gcd(a, b);
}

int dfs(int p) //枚举自由解,只能取0-1,枚举完就回带,找到最小的
{
    if (p<=free_num-1) //深入到了主对角线元素非0 的行了
    {
        //下面就是回带的代码啊
        for(int i = free_num-1; i >= 0; --i)
        {
            int tmp = a[i][var] % 2;
            for(int j = i+1; j < var; ++j) //x[i]取决于x[i+1]--x[var]啊,所以后面的解对前面的解有影
//响。
                if(a[i][j] != 0)
                    tmp = ( tmp - (a[i][j]*x[j])%2 + 2 ) % 2;
            x[i] = (tmp/a[i][i]) % 2; //上面的正常解
        } //回带完成了
//计算解元素为1 的个数;
        int sum=0;
        for(int i=0; i<var; i++) sum+=x[i];
        if (ans>sum) ans=sum;
        return 0;
    }
    x[p]=0;
    dfs(p-1);
    x[p]=1;
    dfs(p-1);
}
void swap(int &a,int &b)
{
    int temp=a;    //交换 2 个数
    a=b;
    b=temp;
}
int Gauss()
{
    int k,col = 0;
//当前处理的列
    for(k = 0; k < equ && col < var; ++k,++col)
    {
        int max_r = k;
        for(int i = k+1; i < equ; ++i)
            if(a[i][col] > a[max_r][col])
                max_r = i;
        if(max_r != k)
        {
            for(int i = k; i < var + 1; ++i)
                swap(a[k][i],a[max_r][i]);
        }
        if(a[k][col] == 0)
        {
            k--;
            continue;
        }
        for(int i = k+1; i < equ; ++i)
        {
            if(a[i][col] != 0)
            {
                int LCM = lcm(a[i][col],a[k][col]);
                int ta = LCM/a[i][col], tb = LCM/a[k][col];
                if(a[i][col]*a[k][col] < 0)
                    tb = -tb;
                for(int j = col; j < var + 1; ++j)
                    a[i][j] = ( (a[i][j]*ta)%2 - (a[k][j]*tb)%2 + 2 ) % 2;
                // 0 和 1 两种状态
            }
        }
    }
//a[i][j]只有

//上述代码是消元的过程,行消元完成
//解下来 2 行,判断是否无解
//注意 K 的值,k 代表系数矩阵值都为 0 的那些行的第 1 行
    for(int i = k; i < equ; ++i)
        if(a[i][col] != 0)
            return -1;
//Debug();

//唯一解或者无穷解,k<=var
//var-k==0 唯一解;var-k>0 无穷多解,自由解的个数=var-k
//能执行到这,说明肯定有解了,无非是 1 个和无穷解的问题。
//下面这几行很重要,保证秩内每行主元非 0,且按对角线顺序排列,就是检查列
    for(int i = 0; i <equ; ++i)//每一行主元素化为非零
        if(!a[i][i])
        {
            int j;
            for(j = i+1; j<var; ++j)
                if(a[i][j])
                    break;
            if(j == var)
                break;
            for(int k = 0; k < equ; ++k)
                swap(a[k][i],a[k][j]);
        }
// ----处理保证对角线主元非 0 且顺序,检查列完成

    free_num=k;
    if (var-k>0)
    {
        dfs(var-1);
        return ans;
        //无穷多解,先枚举解,然后用下面的回带代码进行回带;
//这里省略了下面的回带的代码;不管唯一解和无穷解都可以回带,只不过无穷解
//回带时,默认为最后几个自由变元=0 而已。
    }
    if(var-k<0)
        return -1;
// 无解返回 -1
    if (var-k==0)//唯一解时
    {
//下面是回带求解代码,当无穷多解时,最后几行为 0 的解默认为 0;
        for(int i = k-1; i >= 0; --i) //从消完元矩阵的主对角线非 0 的最后 1 行,开始往
//回带
        {
            int tmp = a[i][var] % 2;

            for(int j = i+1; j < var; ++j) //x[i]取决于 x[i+1]--x[var]啊,所以后面的解对前面的解有影响。
                if(a[i][j] != 0)
                    tmp = ( tmp - (a[i][j]*x[j])%2 + 2 ) % 2;
            //if (a[i][i]==0) x[i]=tmp;//最后的空行时,即无穷解得
            //else
            x[i] = (tmp/a[i][i]) % 2; //上面的正常解
        }
        int sum=0;
        for(int i=0; i<var; i++)
            sum+=x[i];
        return sum;

        //回带结束了
    }
}

int main()
{
    char map[6];
    equ=var=16;
    while(cin>>map)
    {
        memset(a,0,sizeof(a));
        memset(x,0,sizeof(x));
        for(int i=0; i<4; i++)
        {
            if(i)
                cin>>map;
            for(int j=0; j<4; j++)
            {
                int k=i*4+j;
                a[k][k]=1;
                for(int a1=0; a1<4; a1++)
                    for(int b1=0; b1<4; b1++)
                        if(a1==i||b1==j)
                            a[k][a1*4+b1]=1;
                if(map[j]=='+')
                    a[k][16]=1;

            }
        }
        int j1=Gauss();
        cout<<j1<<endl;
        for(int i=0; i<16; i++)
            if(x[i])
                cout<<i/4+1<<' '<<i%4+1<<endl;
    }
    return 0;
}
时间: 2024-08-03 07:13:24

POJ2965高消+搜索的相关文章

POJ1681高消+搜索

Painter's Problem Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 3484   Accepted: 1718 Description There is a square wall which is made of n*n small square bricks. Some bricks are white while some bricks are yellow. Bob is a painter and

POJ1830高消

开关问题 Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 4088   Accepted: 1433 Description 有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开.你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态.对于任意一个开关,最多只能进行一次开关操作

搜索畅想录:从桌面过渡到移动的香饽饽

新时代最受欢迎的当属互联网了,随着科技的迅猛发展,互联网上各种业务层出不穷,可谓百花争艳,各有千秋.而众所周知,人们通过互联网探视整个世界的有效工具就是搜索引擎了.网络刚露尖尖角的时候,兴起的是桌面搜索,在很长的一段时间里,桌面搜索都是占据了主导地位,也方便了网民们的网上冲浪生活. 然而社会在进步,科技在创新,对于搜索引擎来说,新事物的出现也成了人们争相体验的新方式,据某知名科技博主称,目前全球互联网上搜索市场已经发生了明显的转变,这种转变是从夕日桌面搜索到当今移动搜索的转变,这种转变符合互联网

网站信息架构:网站搜索系统

搜索系统:也是一种导航方式,简单的比如一个博客的搜索系统,复杂的比如Google,baidu.当然对于用户检索信息来说应该是最实用的工具之一,只要输入"关键字",然后点击"搜索"按钮就可以完成,但如何给用户有一个匹配度高的搜索结果又是比较复杂的,这又涉及到研究用户体验和交互. [网站需要搜索功能吗?]1.网站内容量多.2.研究搜索系统时,忽略导航系统,分轻重.(当然也些网站是以搜索系统以为主导).3.花时间做搜索结果的优化.4.如果你没有做搜索系统的技术.人才资源.

针对搜索进行写作的基本原则

如何使得站点对搜索引擎有吸引力呢?针对搜索进行写作的最好的基本原则是:"首先要针对人来写,而不是对搜索引擎". 一个普通的搜索营销新手的反应是要对搜索引擎优化所有的东西,往往会走极端地学习每个搜索排名算法的细枝末节,并过度分析和调整自己的站点,用他们能够想到的每一种办法吸引搜索引擎.想要"追赶算法",通过持续不断的重复优化,妄图跟上搜索引擎的每次变化.这是一个大错误.也是徒劳的. 如果你要知道为什么,那么请你回到最基本的地方.你网站的目标是什么?是要得到高的搜索排名

一淘搜索负责人鬼脚七:个性化搜索 影响了谁?

个性化搜索,一个看起来很美,实践起来却很坎坷的偏正短语.在这里你可以看到小而美,可以看到大数据,可以看到大众与长尾的碰撞,也可以看到技术赋予商业的力量. 文/天下网商记者 范婷婷 "天猫搜索的结果中已经加入了个性化的因素,不同的买家ID或者不同的cookie,由于以前的购买或者浏览行为不一样,看到的搜索结果也可能不一样.个性化的算法在搜索结果和营销资源等方面的充分应用,目标是让消费者看到和他最相关的商品展现,最终实现千人千面的天猫."这条天猫CEO逍遥子发于8月2日下午的微博,解释了近

网站跳出率过高最容易被站长忽视

  网站跳出率是体现用户体验好坏的一个重要指标,也是影响关键词排名的一个最为重要的因素之一了.自从百度推出百度统计工具,百度分享之后这个趋势越来越明显了,所以站长们把网站跳出率也看的很重.一旦跳出率过高,就是这里寻找原因那里寻找原因的.笔者也很关注这个问题,今天我发现了一个我以前从来没注意到的问题导致网站跳出率过高.以前也没看到有人谈这个问题,那就是网站跳出率过高跟搜索词不能满足用户需求有关,其实这也不是什么秘密,只是没有意识到而已,今天我就来给大家点破. 以前以为跳出率过高是因为页面质量不能吸

农业网站高PPC点击背后的真相

行业网站的发展从多分类的门户到只做某一产品的细分说明了现在互联网的发展趋势要求网站对于一个行业一个产品更具体的分析,才能得到更高的搜索排名,和客户回访率.而对于国内最庞大的群体,农民对新技术,新知识的了解也逐渐发生着变化,就统计中国农民网民是增长最快的一个群体. 从田间地头的多年经验总结,到今天的跨区域信息交往,南北地区农业生产技术也得到了很好的结合,互联网的发展也改变了农民的传统观念,可以足不出户的了解国内的农作物市场销售行情,种植面积分析,种植与养殖技术的了解,近年来农业网站也发展迅速,而农

搜索框设计技巧分享 帮助优化网站性能

在浏览整个网站中,搜索框通常是通向用户使用的最后一道关卡.如果你的网站内容很多,包含了详尽的特色,功能,设计元素,产品和服务等等,那么搜索框就成为了网站不可或缺的一部分.网站的成长往往需要时间.当然,从整个网站设计和开发过程来看,设计肯定要简洁,有文章和评论,以及非正式的网站通知,特色内容和服务等等.不过,随着网站层次不断提升和更新,与网站相关的内容的只是起到了装饰作用.因此,搜索框对网站的性能优化起到了至关重要的作用.   优质的职能和运作对网站开发确实很重要,但与此同时,我们也不可忽视网站的