【POJ3740】Easy Finding,解题报告+思路+代码

原创 2012年03月21日 21:25:00
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
//#define INPUT
/**
    Problem: poj3740 - Easy Finding
    Begin Time:8:30 p.m. 20th/Mar/2012
    End Time: 8:42 p.m. 21st/Mar/2012
    Last Time: Maybe 4hours-;
    Input:
    Standard output:
    Knowledge point:
    DFS+回溯+剪枝
    State: WA x 1 , TLE x 1  -> AC
    Thought:
    --------------------AC后的总结----------------------
    1.定义一个数组selectedCol,表示目前选出了几列中有"1".
    2.在choose之前,要检查selectedRow[i]是否为true.
      如果是true,这行就选过了,就continue
    3.在每次choose某行的时候,都在choose函数里进行check
    if choose_row[i]  == 1 && selectedCol[i] == 1 return false;
    if choose_row[i] && !selectedCol[i] => selectedCol[i] = 1;
    但是在choose之前记得保存selectedCol的状态,以便return false之前进行回溯。
    4.如果choose失败的话,就要检查是否已经找到了全1,如果找到了
        isFound = true;
        在递归函数里检查isFound = true的话就return true;
    5.如果没找到的话,记得回溯。这就要求在递归函数里每次保存selectedCol的状态,失败了进行回溯。
    6.如果leftRow == 0 ,那么就check,如果check,return true;,否则return false;

    剪枝策略:
        每层递归都是从 i = 0 to rowNum 开始选
        如果上层递归选了i,那就下层递归从i+1开始选。
        因为上层递归从0开始选,选到i的话[0,i]的情况已经由上层递归选完了。
        而且行数跟顺序无关
        比如说
        第一层递归选了1
        那么第二,第三……一直到最后一层递归,肯定是把第一次选1的所有情况都遍历了,
        第一层递归才能去选2
        而且
        1   2   3   4   5   6
        和
        6   5   4   3   2   1
        这么选择是没有区别的,所以下一层递归从ind+1开始就可以了
        加上这个剪枝,653ms就过了。
    更变态的思路:
        由于是0,1我们可以按位表示嘛!然后按照规则算,应该会非常快~
    递归函数定义:
    f(int totalRow,int totalCol,int leftRow,int ind);
    totalRow表示总共有多少行
    totalCol表示列数
    leftRow表示还有几行没选
    int ind表示从现在第几行开始选。
    --------------------AC前的涂鸦----------------------
    其实这道题跟STICK是差不多的,当然,状态压缩是必须的。
    每行压缩成一个数字,然后是否有几个数字相加起来正好等于
    1111111....
    注意,最多可以有10^300,所以这个比较囧!

    每一个状态就是按行i是否被选择来决定,
    选择了某一行之后,就定义tmp[m]对应的列已经被占领。
    那么剩下的就转化为用leftNum - 1行来拼出来其他的列了,如果都能拼出来,那么
    return true,否则return false;
    定义函数f(rowNum,colNum,leftNum);表示总共有rowNum列,有colNum行,剩leftNum没有选
    每次选择的时候定义一个check,看看是否已经选出了每列全有1的行。
    还有一个check2,看看当前选的行是否跟以前的行有冲突。
**/
using namespace std;

int matrix[20][310]; ///开大一点总是没错的
bool selectedCol[310];
bool selectedRow[18];
bool isFound;
bool checked(const int colNum)
{
    for(int i = 0 ; i < colNum ; i++)
    {
        if (!selectedCol[i])
            return false;
    }
    return true;
}
bool choose(const int a[310],int colNum)
{
    int tmp_state[310];
    memset(tmp_state,0,sizeof(tmp_state));
    memcpy(tmp_state,selectedCol,sizeof(tmp_state));
    for(int i = 0 ; i < colNum ; i++)
    {
        if(!selectedCol[i] && a[i] )
        {
            selectedCol[i] = a[i];
        }
        else
        {
            if ( selectedCol[i] && a[i] )
            {
                memcpy(selectedCol,tmp_state,sizeof(tmp_state));
                return false;
            }
        }
    }
    return true;
}
bool Solve(int rowNum,int colNum,int leftNum,int ind)
{
    int tmp_state[310];
    memset(tmp_state,0,sizeof(tmp_state));
    if( isFound )
        return true;
    if (leftNum == 0)
    {
        if ( checked(colNum) )
        {
            isFound = true;
            return true;
        }
        else
        {
            return false;
        }
    }
    for(int i = ind ; i < rowNum ; i++)
    {
        memcpy(tmp_state,selectedCol,sizeof(tmp_state));
        if( isFound ) return true;
        if ( selectedRow[i] ) continue;
        if ( choose(matrix[i],colNum) )
        {
            if( selectedRow[i] != true && !checked(colNum) )
            {
                selectedRow[i] = true;
                Solve(rowNum,colNum,leftNum - 1,i+1);
            }
            else
            {
                if ( checked(colNum) )
                {
                 isFound = true;
                 return true;
                }
            }
       //     memcpy(matrix[i],tmp_state,sizeof(tmp_state));
            memcpy(selectedCol,tmp_state,sizeof(selectedCol));
            selectedRow[i] = false;
        }
      //  selectedRow[i] = false;
    }
    return false;
}
int main()
{
    int n,m;
#ifdef INPUT
    freopen("b:\\acm\\poj3740\\input.txt","r",stdin);
#endif
    while(scanf("%d%d",&m,&n) != EOF )
    {
        isFound = false;
        memset(matrix,0,sizeof(matrix));
        memset(selectedCol,0,sizeof(selectedCol));
        memset(selectedRow,0,sizeof(selectedRow));
        for(int i = 0 ; i < m ; i++)
        {
            for(int j = 0 ; j < n ; j++)
            {
                scanf("%d",&matrix[i][j]);
            }
        }
        if ( Solve(m,n,m,0) )
        {
            printf("Yes, I found it\n");
        }
        else
        {
            printf("It is impossible\n");
        }
    }
    return 0;
}

poj3740 Easy Finding(深搜)

Easy FindingTime Limit: 1000MS Memory Limit: 65536KTotal Submissions: 11432 Accepted: 2802Descriptio...
  • nvfumayx
  • nvfumayx
  • 2011年07月05日 21:58
  • 789

poj3740 Easy Finding DLX

跟上题差不多,还是一个01矩阵,问是否可以选出若干行使得每列恰有一个1。模型都给建好了,直接建表搜就可以了.. #include #include #include #include #in...
  • yanglei040
  • yanglei040
  • 2014年02月09日 23:53
  • 481

POJ3740 Easy Finding(Dancing Links)

G - Easy Finding Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Subm...
  • u014569598
  • u014569598
  • 2014年07月10日 21:00
  • 395

POJ3740 Easy Finding 舞蹈链 DLX

欢迎访问~原文出处——博客园-zhouzhendong&AK 去博客园看该题解 题目 精确覆盖问题模板题 算法 DLX 不会自己学,网上一大堆 代码 #include #includ...
  • zhouzhendongAK
  • zhouzhendongAK
  • 2017年08月03日 20:37
  • 147

pku3740 Easy Finding (搜索)

 给一个M*N的矩阵,矩阵元素均为0, 1问是否可以选出一些行,使得这些行的每一行有且仅有一个1例如 中的1, 4, 5行满足这个条件这里的数据规模比较小,直接深度搜索就可以。 #include #...
  • vecri
  • vecri
  • 2009年11月19日 23:54
  • 413

poj——3740 Easy Finding

POJ - 3740 Easy Finding Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %...
  • qq_30927651
  • qq_30927651
  • 2016年06月08日 15:24
  • 418

【POJ】3740 Easy Finding 精确覆盖入门题

传送门:【POJ】3740 Easy Finding 题目分析:
  • u013368721
  • u013368721
  • 2014年07月28日 17:04
  • 809

HDU 1254 推箱子 解题报告

HDU 1254的解题报告
  • lawk97
  • lawk97
  • 2016年09月05日 10:17
  • 391

【POJ3740】Easy Finding DLX(Dancing Links)精确覆盖问题

Dancing Links(DLX)的个人心得。
  • Vmurder
  • Vmurder
  • 2014年10月29日 15:11
  • 1449

Finding Tiny Faces

Overview of detection pipeline Multi-task modeling of scales 前面a, b两种是传统的 model 方式。 b的缺...
  • smallplum123
  • smallplum123
  • 2016年12月21日 23:23
  • 2018
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【POJ3740】Easy Finding,解题报告+思路+代码
举报原因:
原因补充:

(最多只允许输入30个字)