자료 DFS (POJ 1321, hdoj 2553, 5113 hdoj)

화이트는 헤이 헤이 헤이, 오늘의 질문은, 기록하려는 DFS를 배웠다

용량 1,321

체스 판
시간 제한 : 1000MS 메모리 제한 : 10000K
제출에 총 : 85,425 허용 : 39462

기술

조각 조각 이상 차이가 배치되지 바둑판 소정 형상 (모양이 불규칙적 일 수있다)이다. 디스플레이가 요구되는 경우 두 가지의 요구 사항은 모든 가능한 배치 방식 (C)의 K 개를 소정의 기판의 크기 및 형상을 해결 배치하는, 동일한 행 또는 보드에서 동일한 열에있는 프로그램을 배치 할 수 없다

입력

데이터의 복수의 세트를 포함하는 테스트 입력.
각 데이터의 첫 번째 줄의 공간에 의해 분리 된 두 개의 양의 정수, NK을하며, 보드의 개수는 N * N 매트릭스에 대하여 설명한다 나타내고, 조각을 넣어. N <= 8, K <= N
입력의 끝은 -1로 표시되는 경우 -1.
그런 다음 n 개의 라인들 바둑판 모양 설명 : N #은 보드 공간을 나타내는 라인 당 문자를 빈 영역 (여분의 빈 줄 데이터가 나타나거나 빈 열을하지 않는 보장)을 나타냅니다.

산출

데이터의 각 세트에 대해, 하나 개의 출력 라인은, 디스플레이 출력 프로그램 C의 번호가 부여된다 (데이터는 C ^ 31 <2을 보장한다).

샘플 입력

2 1
#.
. #
4 4
... #
... #.
. # ...
# ...
-1 -1

샘플 출력

2
1

DFS 새로운 화이트, 확실히이 일을 이해하지, 난 층으로 좋은 마법 재귀 계층 느낌 , 또는 좀 더 이해 필요, 더 많은 연습 아! DFS 코드는 BFS보다 짧은,하지만 이해하기 쉽게하지, 예를 문제점을 여전히 많이있다.

#include <iostream>
#include <string.h>
using namespace std;
char maps[9][9];//读取棋盘
int lie[9],ans=0,k,n,m=0;
void dfs(int row)
{
    if(row>n)//超出棋盘范围则返回
        return;
    if(m==k)//当搜索长度与要求的相同时,返回
    {
        ans++;
        return;
    }
    for(int i=0;i<n;i++)
    {
        if(maps[row][i]=='#'&&lie[i]==0)
        {
            lie[i]=1;
            m++;
            dfs(row+1);
            m--;//恢复之前的状态
            lie[i]=0;
        }
    }
    dfs(row+1);//下一行
}
int main()
{
    while(cin>>n>>k&&n!=-1)
    {
        ans=0;m=0;
        memset(maps,0,sizeof(maps));
        memset(lie,0,sizeof(lie));
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
                cin>>maps[i][j];
        }
        dfs(0);
        cout<<ans<<endl;
    }
}

자연 상태 방문하지 않습니다에 더 이해 필요, 다음은 계층 재귀 리턴 오른쪽 지점을 찾는 것입니다 상태를 복원 한 후 다음 층을 복원 할 수 있습니다.

2,553 hdoj N 퀸 문제점

효과에 제목 : 이 질문은 배치 N 보드에 여왕이 그들에게 배치 방법을 얼마나 많은 문의 다른 행과 다른 열, 다른 대각선을 만들기 위해 비교적 간단한 N 퀸즈, 즉 N 퀸즈 10.00이다.

해결 방법 : 사용 DFS이 문제의 필요를 검색,하는 것이 중요하다 뒤로 치기 이동 요구 사항을 충족하지 않는 배치 방법을 제거, 예. 당신이 테이블 시간을 명중하지 않는 경우 첫째, 테이블 싸움, 다음에서 다른 대각선 여기, 요구 사항을 충족 할 것인지 여부를 결정하는 기능을 점검 한 다음 검색 DFS 사용하고 (난, j)에 향사는 (단계, 새로운 좌표를 걸어 대각선 R, C)의 4 개의 경우가있다 : (IA, JA), ( IA, J + a), (I + A, JA), (I + A, J + a). 요약하자면, | 적외선 | = | JC |

AC 코드 :

#include <iostream>
#include <string.h>
#include <cmath>
using namespace std;
int col[12]={0};
int ans[12]={0};
int n,sum=0;
bool check(int c,int r)
{
    for(int i=0;i<r;i++)//从每一排检查该列有没有已经放下的
    {
        if(col[i]==c||abs(col[i]-c)==abs(i-r))
            return false;
    }
    return true;
}
void dfs(int r)
{
    if(r==n)
    {
        sum++;
        return;
    }
    for(int i=0;i<n;i++)//每一列
    {
        if(check(i,r))
        {
            col[r]=i;
            dfs(r+1);
        }
    }
}
int main()
{
    for(n=0;n<=10;n++)//先打表
    {
        memset(col,0,sizeof(col));
        sum=0;
        dfs(0);//从第0排开始搜索
        ans[n]=sum;
    }
    while(cin>>n&&n)
    {
        cout<<ans[n]<<endl;
    }
}

5113 hdoj 흑백이
(이 문제의 대부분은 쓰기 EMM에, 그러나 dalao 코드를 볼 제거 할 때)

타이틀 효과 : 착색 문제는, 두 개의 인접 지역이 동일 색상 (즉, 공용 영역의 한쪽) 수 있고, 각각의 컬러의 발생 횟수와 블록 수 및 다양한 색상이 나타날 수의 총합을 명시 할 수 없다. 질문의 의미에 부합하는 착색 방법을 작성합니다.

해결 방법 : 모든 후, 처음으로 자신의 DFS를 작성, 중간 많은 사소한 버그가 있었다. 지도의 배열을 쓸 때이 지역의 일부 색상을 넣을 수 있습니다 여부를 결정할 때, 인덱스가 1보다 편리부터 시작하는 것이 좋습니다. 전체 아이디어는 거절 후, 시작 DFS는 (1,1)에서 검색, 사용하는이 프로그램은, 재귀는 롤백됩니다 가능하지 않은 경우 판사에 색상을 적용하는 것입니다. 이 마지막 할 수있는 검색 가능한 경우에, 당신은 롤백 복귀 하나를 추가해야합니다.
제거 할 때 특정 색상의 블록의 나머지 숫자는 일반적으로 적은 색상의 나머지 수보다 경우, 반드시 가능한이 방식은 (자신의 그림이 나왔다에 dalao 코드를 볼 말한다).

AC 코드 :

#include <iostream>
#include <string.h>
using namespace std;
int maps[6][6];
int num[26];
int tmp[26];
int n,m,k;
int dfs(int r,int c)
{
    int flag=0;
    if(r==n+1)
    {
        return 1;
    }
    int sum=(n*m-(r-1)*m-c+2)/2; //剪枝
    for(int i=1;i<=k;i++)
    {
        if(num[i]-tmp[i]>sum)
            return 0;
    }
    for(int i=1;i<=k;i++)
    {
        if(tmp[i]>=num[i]||maps[r][c-1]==i||maps[r-1][c]==i)
            continue;
        maps[r][c]=i;
        tmp[i]++;
        if(c==m)
            flag=dfs(r+1,1);
        else
            flag=dfs(r,c+1);
        if(flag==1)//回退时,如果方案可行,则需要返回1
            return 1;
        tmp[i]--; //不要忘记回到之前的状态
        maps[r][c]=0;
    }
    return 0;
}
int main()
{
    int w,t=0;
    cin>>w;
    while(w--)
    {
        memset(maps,0,sizeof(maps));
        memset(tmp,0,sizeof(tmp));
        t++;
        cin>>n>>m>>k;
        for(int i=1;i<=k;i++)
        {
            cin>>num[i];
        }
        cout<<"Case #"<<t<<":"<<endl;
        int flag=dfs(1,1);
        if(flag==0)
            cout<<"NO"<<endl;
        else
        {
            cout<<"YES"<<endl;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    cout<<maps[i][j];
                    if(j==m)
                        cout<<endl;
                    else
                        cout<<" ";
                }
            }
        }
    }
}
게시 32 개 원래 기사 · 원의 찬양 (12) · 전망 1383

추천

출처blog.csdn.net/qq_18873031/article/details/98495609