Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_36480062
Algorithm
提交
134d6e34
A
Algorithm
项目概览
qq_36480062
/
Algorithm
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
Algorithm
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
134d6e34
编写于
9月 27, 2020
作者:
qq_36480062
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
c
上级
9f2a7a56
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
146 addition
and
25 deletion
+146
-25
ACWing/src/dp/状态压缩dp/骑士.java
ACWing/src/dp/状态压缩dp/骑士.java
+29
-25
ACWing/src/dp/状态压缩dp/骑士y.java
ACWing/src/dp/状态压缩dp/骑士y.java
+117
-0
未找到文件。
ACWing/src/dp/状态压缩dp/骑士.java
浏览文件 @
134d6e34
...
...
@@ -42,60 +42,64 @@ import java.util.Scanner;
* f[i,j,k] k为二进制数,表示在哪里放了国王
* 状态定义:所有只从前i行摆放,已经摆了j个国王,并且第i行的摆放状态是k的所有方案的集合
* 属性count
* 状态是k要满足,
* 1.第i-1行内部不能有两个1相邻, 通过k&(k>>1)!=1代表合法
* 2.第i-1行和第i行也不能相互攻击到
* a代表i-1行,b代表i行,(a&b==0并且a|b也不能有相邻的1)代表合法
* 3.
*/
public
class
骑士
{
public
static
void
main
(
String
[]
args
)
{
for
(
int
i
=
0
;
i
<
head
.
length
;
i
++)
{
head
[
i
]
=
new
ArrayList
<
Integer
>();
}
Scanner
sc
=
new
Scanner
(
System
.
in
);
n
=
sc
.
nextInt
();
m
=
sc
.
nextInt
();
for
(
int
i
=
0
;
i
<
1
<<
n
;
i
++)
{
if
(
check
(
i
))
{
a
.
add
(
i
);
//去除相邻的放置方法
cnt
.
add
(
count
(
i
));
//预处理i
作为
state
.
add
(
i
);
//去除相邻的放置方法
cnt
.
add
(
count
(
i
));
//预处理i
的1的数量
}
}
int
s
=
0
,
t
=
0
,
u
=
0
;
for
(
int
i
=
0
;
i
<
a
.
size
();
i
++)
{
for
(
int
j
=
0
;
j
<
a
.
size
();
j
++)
{
s
=
a
.
get
(
i
);
t
=
a
.
get
(
j
);
if
((
s
&
t
)
==
0
&&
check
(
s
|
t
))
b
[
s
].
add
(
t
);
for
(
int
i
=
0
;
i
<
state
.
size
();
i
++)
{
for
(
int
j
=
0
;
j
<
state
.
size
();
j
++)
{
s
=
state
.
get
(
i
);
t
=
state
.
get
(
j
);
if
((
s
&
t
)
==
0
&&
check
(
s
|
t
))
head
[
s
].
add
(
t
);
//去除s&t(i-1行&i)两行之内有相同元素
//check(s|t)把有1的全部置为1,如果有相邻1说明对角线为1
//预处理所有方案
}
}
f
[
0
][
0
][
0
]
=
1
;
for
(
int
i
=
1
;
i
<=
n
;
i
++)
{
for
(
int
i
=
1
;
i
<=
n
+
1
;
i
++)
{
for
(
int
j
=
0
;
j
<=
m
;
j
++)
{
//枚举个数
for
(
int
k
=
0
;
k
<
a
.
size
();
k
++)
{
t
=
a
.
get
(
k
);
//取出作为第i行
for
(
s
=
0
;
s
<
b
[
t
].
size
();
s
++)
{
u
=
b
[
t
].
get
(
s
);
//枚举与t不冲突的u
for
(
int
k
=
0
;
k
<
state
.
size
();
k
++)
{
t
=
state
.
get
(
k
);
//取出作为第i行
for
(
s
=
0
;
s
<
head
[
t
].
size
();
s
++)
{
u
=
head
[
t
].
get
(
s
);
//枚举与t不冲突的u
if
(
j
>=
cnt
.
get
(
k
))
//第i行的骑士个数要合法
f
[
i
][
j
][
t
]
+=
f
[
i
-
1
][
j
-
cnt
.
get
(
k
)][
u
];
}
}
}
}
System
.
out
.
println
(
f
[
n
+
1
][
m
][
0
]);
long
res
=
0
;
for
(
int
i
=
0
;
i
<
a
.
size
();
i
++)
{
res
+=
f
[
n
][
m
][
a
.
get
(
i
)];
for
(
int
i
=
0
;
i
<
state
.
size
();
i
++)
{
res
+=
f
[
n
][
m
][
state
.
get
(
i
)];
}
System
.
out
.
println
(
res
);
}
static
int
n
,
m
;
static
long
[][][]
f
=
new
long
[
12
][
105
][
1
<<
12
];
static
ArrayList
<
Integer
>[]
b
=
new
ArrayList
[
1
<<
12
];
static
ArrayList
<
Integer
>[]
head
=
new
ArrayList
[
1
<<
12
];
static
{
for
(
int
i
=
0
;
i
<
b
.
length
;
i
++)
{
b
[
i
]
=
new
ArrayList
<
Integer
>();
}
}
static
ArrayList
<
Integer
>
a
=
new
ArrayList
<
Integer
>();
static
ArrayList
<
Integer
>
state
=
new
ArrayList
<
Integer
>();
static
ArrayList
<
Integer
>
cnt
=
new
ArrayList
<
Integer
>();
static
boolean
check
(
int
st
)
{
...
...
@@ -104,11 +108,11 @@ public class 骑士 {
}
//计算该行有多少个1
static
int
count
(
int
n
)
{
static
int
count
(
int
state
)
{
int
res
=
0
;
while
(
n
!=
0
)
{
if
((
n
&
1
)
==
1
)
res
++;
n
>>=
1
;
while
(
state
!=
0
)
{
res
++;
state
-=
(
state
&
-
state
)
;
}
return
res
;
}
...
...
ACWing/src/dp/状态压缩dp/骑士y.java
0 → 100644
浏览文件 @
134d6e34
package
dp.
状态压缩dp
;
import
java.util.ArrayList
;
import
java.util.Scanner
;
/**
* f[i,j,k]状态表示:所有只摆在前i行,已经摆了j个国王,并且第i行的摆放状态是k所有方案的集合
* 属性count
* 状态计算:
* 当前行状态已经有了,就是k
* 考虑当前层的上一层是什么状态
* 划分依据,根据上一层的状态是什么,把集合分成若干类
* 枚举上一层状态是什么,最多2^m种方案,但被预处理了没有这么高
* 考虑第i-1行需要满足什么条件才能转移到第i行,也就是第i-1行不与第i行冲突
* 首先第i-1行要满足:没有相邻的两个1
* 还需要满足,第i-1行与第i行不能相互攻击到
* 如何实现呢,i-1行的状态是a,第i行状态为b a&b==0 表示没有一列有两个国王
* 且a|b不能有相邻的两个1,
* 如果第i-1行是合法的,直接加上这一类的元素数量即可
* <p>
* 已经摆完了前i排,并且第i行状态是a,第i-1行状态是b,已经摆了j个国王的所有方案
* 已经摆完了前i-1排,并且i-1行状态是b,已经摆了j-count(a)个国王的所有方案, f[ i-1 , j-count(a) , b ]
*/
public
class
骑士y
{
public
static
void
main
(
String
[]
args
)
{
for
(
int
i
=
0
;
i
<
head
.
length
;
i
++)
{
head
[
i
]
=
new
ArrayList
<
Integer
>();
}
Scanner
sc
=
new
Scanner
(
System
.
in
);
n
=
sc
.
nextInt
();
m
=
sc
.
nextInt
();
for
(
int
i
=
0
;
i
<
1
<<
n
;
i
++)
{
if
(
check
(
i
))
{
state
.
add
(
i
);
cnt
[
i
]
=
count
(
i
);
}
}
//预处理两个状态之间的转移关系,哪个状态之间可以转移
for
(
int
i
=
0
;
i
<
state
.
size
();
i
++)
{
for
(
int
j
=
0
;
j
<
state
.
size
();
j
++)
{
int
a
=
state
.
get
(
i
),
b
=
state
.
get
(
j
);
//第i-1行与第i行不能相互攻击到,内部不冲突,前面已经判断
if
(((
a
&
b
)
==
0
)
&&
check
(
a
|
b
))
{
head
[
a
].
add
(
b
);
}
}
}
f
[
0
][
0
][
0
]
=
1
;
// for (int i = 1; i <= n + 1; i++) {//枚举每一行
// for (int j = 0; j <= m; j++) {//国王数量
// for (int a = 0; a < state.size(); a++) {
// s = state.get(a);
// for (Integer b : head[a]) {
// int c = cnt[state.get(a)];
// if (j >= c) {
// f[i][j][s] +=f[i - 1][j - c][b];
// }
// }
// }
// }
// }
int
s
,
t
,
u
;
for
(
int
i
=
1
;
i
<=
n
+
1
;
i
++)
{
for
(
int
j
=
0
;
j
<=
m
;
j
++)
{
//枚举个数
for
(
int
k
=
0
;
k
<
state
.
size
();
k
++)
{
t
=
state
.
get
(
k
);
//取出作为第i行
for
(
s
=
0
;
s
<
head
[
t
].
size
();
s
++)
{
u
=
head
[
t
].
get
(
s
);
//枚举与t不冲突的u
if
(
j
>=
cnt
[
k
])
//第i行的骑士个数要合法
f
[
i
][
j
][
t
]
+=
f
[
i
-
1
][
j
-
cnt
[
k
]][
u
];
}
}
}
}
System
.
out
.
println
(
f
[
n
+
1
][
m
][
0
]);
long
res
=
0
;
for
(
int
i
=
0
;
i
<
state
.
size
();
i
++)
{
res
+=
f
[
n
][
m
][
state
.
get
(
i
)];
}
System
.
out
.
println
(
res
);
}
static
int
count
(
int
state
)
{
int
res
=
0
;
while
(
state
!=
0
)
{
res
++;
state
-=
(
state
&
-
state
);
}
return
res
;
}
/**
* 检查状态是否存在连续的两个1
*
* @param state 状态
*/
static
boolean
check
(
int
state
)
{
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
if
((
state
>>
i
&
1
)
==
1
&&
(
state
>>
i
+
1
&
1
)
==
1
)
{
return
false
;
}
}
return
true
;
}
static
int
n
,
m
,
N
=
12
,
M
=
1
<<
10
,
K
=
110
;
//K是国王数量
static
ArrayList
<
Integer
>
state
=
new
ArrayList
<
Integer
>();
static
ArrayList
<
Integer
>[]
head
=
new
ArrayList
[
M
];
static
int
[]
cnt
=
new
int
[
M
];
//每个状态1的个数
static
long
[][][]
f
=
new
long
[
N
][
K
][
M
];
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录