ホワイトはまたちょっとちょっとちょっと、今日の質問は、記録したいDFSを学びました
チェス盤
制限時間:1000msのメモリ制限:10000K
提出の合計:85425受理:39462
説明
チェッカーボードにおいて片、個ない差の上方に配置さ(形状が不規則であってもよい)の形状を与えられ。任意の二枚の表示が要求される場合、同じ行またはボードにおいて同一列に配置することができない、所与の基板サイズ及び形状を解決するためのプログラムの要件は、すべての可能な配置スキームCのk個を配置すること
入力
データの複数のセットを含むテスト入力。
各データの最初の行は、スペースで区切られた2つの正の整数、NKを、であり、ボードの数はN * Nの行列に説明する表し、ピースを置きます。N <= 8、K <= N
の入力端が-1で表される場合-1。
その後、n行市松模様の形状について説明:N#は基板面積を表す行あたりの文字を、空白領域(余分な空白行のデータが表示されるか、空欄ないことが保証されている)を示しています。
出力
データの各セットに対して、出力の1本のラインを、出力表示プログラム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;
}
}
どこの必要性がより理解状態を復元し、それはその後、自然な状態に復元するための次の層が訪問されていない、層の再帰的なリターンの後に右のポイントを見つけることです。
2553 hdoj Nクイーン問題
効果の件名:この質問は、お問い合わせは、配置方法を持っているどのように多くの比較的単純なNクイーン、すなわちNクイーン10.00、それら異なる行および異なる列にするボード上の配置Nクイーン、異なる対角線、です。
解決策:使用DFS検索するには、この問題の必要性、それがすることが重要である背中や剪定て行く、すなわち配置方法を除去することが要件を満たしていません。最初のテーブルを戦うあなたがテーブルの時間をヒットし、[検索DFSを使用して、要件を満たしているかどうかを判断するための機能をチェックしていない場合は、ここでは異なる対角線でから(i、j)の向斜は、ステップ、新しい座標を(歩い対角線R、C)は、4つの場合がある:(IA、JA)、( IA、J +)、(I +、JA)、(I +、J +)。要するに、| IR | = | 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、より便利で開始することをお勧めします。全体的なアイデアは、起動し、その後下げ、このプログラムは実行不可能である場合は裁判官に色を適用するには(1,1)から、DFS検索を使用することで、再帰的なバックをロールバックされます。これを最後まで検索が可能である場合は、ロールバックのリターン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<<" ";
}
}
}
}
}