デジタルdpソリューション:
A.特別なチェッカーボード
-
タイトル:\(n \×n \)
n
でチェッカーボードに車を置きます。いくつかの正方形を配置できません。それらが互いに攻撃するのを防ぐための解決策の総数を求めてください。注:同じ行または列に配置できる車は1台だけです。それ以外の場合、お互いを攻撃します。 -
分析:
- まず、同じライン間で攻撃が発生しないようにするために、各ラインが一度に1ラインずつ配置されている限り、ラインごとに1台の車しか存在できません。
- 次に、各列に車を1つだけ配置できます。どの列に車があるかを記録できる限り、次回はこの列を考慮する必要はありません。
- 2進数
S
を使用して、車が列に配置されているかどうかを示します。たとえばn=5, S=01101
は、1列目、3列目、4列目(低い位置から開始)が車を配置したことを意味します。最終的S=11111
に、州内の解の数がわかります。 - 定義
f[s]
は、州s
のシナリオの数を表します。\(s \ in [0 \ sim 2 ^ n-1] \)- 仮定
s=01101
、明らかに:f[01101]= f[01100]+f[01001]+f[00101]
- しかし、現在の場所に障害がある場合はどうなりますか?そのため、再び車を置くときに、現在位置に障害物があるかどうかを判断します。特定の実装については、コードを参照してください。
- 仮定
-
コードの実装:
#include<bits/stdc++.h> const int maxn=(1<<20)-1; typedef long long LL; LL f[maxn],a[25];//a[x]记录第x行的障碍状态 int lowbit(int x){return x & -x;}; int main(){ int n,m;scanf("%d%d",&n,&m); for(int i=1;i<=m;++i){ int x,y;scanf("%d%d",&x,&y); a[x]+=1<<(y-1); } f[0]=1;//一个也不放也是一种方案 int maxs=1<<n;//最大的状态 for(int S=1;S<maxs;++S){//从状态1开始枚举 int cnt=0;//计算状态S里的1的个数,几个1说明处理到第几行 for(int i=S;i;i-=lowbit(i))cnt++; for(int i=S;i;i-=lowbit(i)){//依次判断当前状态每一个1 if(!(a[cnt] & lowbit(i))){//状态S当前的1所在列如果没有障碍 int s=S^lowbit(i);//说明lowbit(i)处可以放车,当前就在此处放车 f[S]+=f[s];//s<S,保证能转移 } } } printf("%lld\n",f[maxs-1]); return 0; }
B.非攻撃性
- 質問の意味:に\(nは\ n倍\)に置くボード
n
の王を、彼らはお互いを攻撃しないように、種のプログラムの合計数を置きます。王はそれを上、下、左、右、左上、右下、右上、右下、そして近くの8方向のそれぞれのグリッドに攻撃できます。 - 分析:
- この質問は、先ほど説明したトウモロコシ畑の例とよく似ています。障害は少なくなりますが、数の制限が増えます。通常、制限がもう1つある場合は、1つの次元の状態を増やします。
- 王を
dp[ i ][ j ][ k ]
最初のi
列に配置した状態をj
ボード上k
の計画の数とする。 - ステージは明白です。つまり、行ごとに処理できます。最初の行は特別で、前処理できます
- 判断の矛盾:
s
現在の行s'
が前の行であるとします。- 行の競合、つまり隣接することはできません。判断するだけで
(s & (s<<1))==0
、ゼロ以外は隣接することを意味します。 - 列の競合:
- 逆さまの衝突:
(s & s')==0
0でない場合、裁判官は、逆さまの衝突を意味します。 - 左上の衝突:裁判官
((s<<1) & s')==0
、そうでない場合は0
、衝突について説明します。 - 右上の衝突:裁判官
((s>>1) & s')==0
、そうでない場合は0
、衝突を説明します。
- 逆さまの衝突:
- 現在の状態の状態
1
数を判別するには、lowbitを使用します。
- 行の競合、つまり隣接することはできません。判断するだけで