当前位置:网站首页>2022-06-12:在N*N的正方形棋盤中,有N*N個棋子,那麼每個格子正好可以擁有一個棋子。 但是現在有些棋子聚集到一個格子上了,比如: 2 0 3 0 1 0 3 0 0 如上的二維數組代錶,一
2022-06-12:在N*N的正方形棋盤中,有N*N個棋子,那麼每個格子正好可以擁有一個棋子。 但是現在有些棋子聚集到一個格子上了,比如: 2 0 3 0 1 0 3 0 0 如上的二維數組代錶,一
2022-06-13 06:50:00 【福大大架構師每日一題】
2022-06-12:在NN的正方形棋盤中,有NN個棋子,那麼每個格子正好可以擁有一個棋子。
但是現在有些棋子聚集到一個格子上了,比如:
2 0 3
0 1 0
3 0 0
如上的二維數組代錶,一共3*3個格子,
但是有些格子有2個棋子、有些有3個、有些有1個、有些沒有,
請你用棋子移動的方式,讓每個格子都有一個棋子,
每個棋子可以上、下、左、右移動,每移動一步算1的代價。
返回最小的代價。
來自微軟。
答案2022-06-12:
km算法,距離取負數。
代碼用rust編寫。代碼如下:
use rand::Rng;
fn main() {
let len: i32 = 4;
let test_time: i32 = 1000;
println!("測試開始");
for _ in 0..test_time {
let mut graph = random_valid_matrix(len);
let ans1 = min_distance1(&mut graph);
let ans2 = min_distance2(&mut graph);
if ans1 != ans2 {
println!("出錯了!");
println!("ans1 = {}", ans1);
println!("ans2 = {}", ans2);
println!("===============");
}
}
println!("測試結束");
}
// 暴力解
// 作為對數器
fn min_distance1(map: &mut Vec<Vec<i32>>) -> i32 {
let mut n = 0;
let mut m = 0;
for i in 0..map.len() as i32 {
for j in 0..map[0].len() as i32 {
n += get_max(0, map[i as usize][j as usize] - 1);
m += if map[i as usize][j as usize] == 0 {
1
} else {
0
};
}
}
if n != m || n == 0 {
return 0;
}
let mut nodes: Vec<Vec<i32>> = vec![];
for i in 0..n {
nodes.push(vec![]);
for _ in 0..2 {
nodes[i as usize].push(0);
}
}
let mut space: Vec<Vec<i32>> = vec![];
for i in 0..m {
space.push(vec![]);
for _ in 0..2 {
space[i as usize].push(0);
}
}
n = 0;
m = 0;
for i in 0..map.len() as i32 {
for j in 0..map[0].len() as i32 {
for _k in 2..map[i as usize][j as usize] {
nodes[n as usize][0] = i;
nodes[n as usize][1] = j;
n += 1;
}
if map[i as usize][j as usize] == 0 {
space[m as usize][0] = i;
space[m as usize][1] = j;
m += 1;
}
}
}
return process1(&mut nodes, 0, &mut space);
}
fn process1(nodes: &mut Vec<Vec<i32>>, index: i32, space: &mut Vec<Vec<i32>>) -> i32 {
let mut ans = 0;
if index == nodes.len() as i32 {
for i in 0..nodes.len() as i32 {
ans += distance(&mut nodes[i as usize], &mut space[i as usize]);
}
} else {
ans = 2147483647;
for i in index..nodes.len() as i32 {
swap(nodes, index, i);
ans = get_min(ans, process1(nodes, index + 1, space));
swap(nodes, index, i);
}
}
return ans;
}
fn swap(nodes: &mut Vec<Vec<i32>>, i: i32, j: i32) {
let tmp = nodes[i as usize].clone();
nodes[i as usize] = nodes[j as usize].clone();
nodes[j as usize] = tmp.clone();
}
fn distance(a: &mut Vec<i32>, b: &mut Vec<i32>) -> i32 {
return abs(a[0] - b[0]) + abs(a[1] - b[1]);
}
fn abs(a: i32) -> i32 {
if a < 0 {
-a
} else {
a
}
}
// 正式方法
// KM算法
fn min_distance2(map: &mut Vec<Vec<i32>>) -> i32 {
let mut n = 0;
let mut m = 0;
for i in 0..map.len() as i32 {
for j in 0..map[0].len() as i32 {
n += get_max(0, map[i as usize][j as usize] - 1);
m += if map[i as usize][j as usize] == 0 {
1
} else {
0
};
}
}
if n != m || n == 0 {
return 0;
}
let mut nodes: Vec<Vec<i32>> = vec![];
for i in 0..n {
nodes.push(vec![]);
for _ in 0..2 {
nodes[i as usize].push(0);
}
}
let mut space: Vec<Vec<i32>> = vec![];
for i in 0..m {
space.push(vec![]);
for _ in 0..2 {
space[i as usize].push(0);
}
}
n = 0;
m = 0;
for i in 0..map.len() as i32 {
for j in 0..map[0].len() as i32 {
for _k in 2..=map[i as usize][j as usize] {
nodes[n as usize][0] = i;
nodes[n as usize][1] = j;
n += 1;
}
if map[i as usize][j as usize] == 0 {
space[m as usize][0] = i;
space[m as usize][1] = j;
m += 1;
}
}
}
let mut graph: Vec<Vec<i32>> = vec![];
for i in 0..n {
graph.push(vec![]);
for _ in 0..n {
graph[i as usize].push(0);
}
}
for i in 0..n {
for j in 0..n {
graph[i as usize][j as usize] =
-distance(&mut nodes[i as usize], &mut space[j as usize]);
}
}
return -km(&mut graph);
}
fn get_max<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a > b {
a
} else {
b
}
}
fn get_min<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a < b {
a
} else {
b
}
}
fn km(graph: &mut Vec<Vec<i32>>) -> i32 {
let nn = graph.len() as i32;
let mut match0: Vec<i32> = vec![];
let mut lx: Vec<i32> = vec![];
let mut ly: Vec<i32> = vec![];
// dfs過程中,碰過的點!
let mut x: Vec<bool> = vec![];
let mut y: Vec<bool> = vec![];
// 降低的預期!
// 公主上,打一個,降低預期的值,只維持最小!
let mut slack: Vec<i32> = vec![];
let mut falsev: Vec<bool> = vec![];
for _ in 0..nn {
match0.push(0);
lx.push(0);
ly.push(0);
x.push(false);
y.push(false);
slack.push(0);
falsev.push(false);
}
let invalid = 2147483647;
for i in 0..nn {
match0[i as usize] = -1;
lx[i as usize] = -invalid;
for j in 0..nn {
lx[i as usize] = get_max(lx[i as usize], graph[i as usize][j as usize]);
}
ly[i as usize] = 0;
}
for from in 0..nn {
for i in 0..nn {
slack[i as usize] = invalid;
}
x = falsev.clone();
y = falsev.clone();
// dfs() : from王子,能不能不降預期,匹配成功!
// 能:dfs返回true!
// 不能:dfs返回false!
while !dfs(
from,
&mut x,
&mut y,
&mut lx,
&mut ly,
&mut match0,
&mut slack,
graph,
) {
// 剛才的dfs,失敗了!
// 需要拿到,公主的slack裏面,預期下降幅度的最小值!
let mut d = invalid;
for i in 0..nn {
if !y[i as usize] && slack[i as usize] < d {
d = slack[i as usize];
}
}
// 按照最小預期來調整預期
for i in 0..nn {
if x[i as usize] {
lx[i as usize] = lx[i as usize] - d;
}
if y[i as usize] {
ly[i as usize] = ly[i as usize] + d;
}
}
x = falsev.clone();
y = falsev.clone();
// 然後回到while裏,再次嘗試
}
}
let mut ans = 0;
for i in 0..nn {
ans += lx[i as usize] + ly[i as usize];
}
return ans;
}
// from, 當前的王子
// x,王子碰沒碰過
// y, 公主碰沒碰過
// lx,所有王子的預期
// ly, 所有公主的預期
// match,所有公主,之前的分配,之前的爺們!
// slack,連過,但沒允許的公主,最小下降的幅度
// map,報價,所有王子對公主的報價
// 返回,from號王子,不降預期能不能配成!
fn dfs(
from: i32,
x: &mut Vec<bool>,
y: &mut Vec<bool>,
lx: &mut Vec<i32>,
ly: &mut Vec<i32>,
match0: &mut Vec<i32>,
slack: &mut Vec<i32>,
map: &mut Vec<Vec<i32>>,
) -> bool {
let nn = map.len() as i32;
x[from as usize] = true;
for to in 0..nn {
if !y[to as usize] {
// 只有沒dfs過的公主,才會去嘗試
let d = lx[from as usize] + ly[to as usize] - map[from as usize][to as usize];
if d != 0 {
// 如果當前的路不符合預期,更新公主的slack值
slack[to as usize] = get_min(slack[to as usize], d);
} else {
// 如果當前的路符合預期,嘗試直接拿下,或者搶奪讓之前的安排倒騰去
y[to as usize] = true;
if match0[to as usize] == -1
|| dfs(match0[to as usize], x, y, lx, ly, match0, slack, map)
{
match0[to as usize] = from;
return true;
}
}
}
}
return false;
}
// 為了測試
fn random_valid_matrix(len: i32) -> Vec<Vec<i32>> {
let mut graph: Vec<Vec<i32>> = vec![];
for i in 0..len {
graph.push(vec![]);
for _ in 0..len {
graph[i as usize].push(0);
}
}
let all = len * len;
for _i in 1..all {
graph[rand::thread_rng().gen_range(0, len) as usize]
[rand::thread_rng().gen_range(0, len) as usize] += 1;
}
return graph;
}
執行結果如下:
边栏推荐
- Introduction to applet layout
- YOLOv5解析 | 参数与性能指标
- Scrcpy development environment construction and source code reading
- 【马尔科夫链-蒙特卡罗】马尔科夫链-蒙特卡罗方法对先验分布进行抽样
- Common method of props changing value V-model sync
- Cocos released the oppo game prompt "subcontracting failed"
- 15、 IO stream (I)
- Select all select none JS code implementation
- ML:机器学习模型的稳定性分析简介、常见的解决方法之详细攻略
- What is the new business model of Taishan crowdfunding in 2022?
猜你喜欢
The innovative public platoon mode team invites users to split, beautiful every second, and links the 2+1 new business model
玄武云科技通过上市聆讯:业绩波动明显,陈永辉等三人为控股股东
[system analysis and design] college student association management system
Intelligent entertainment has developed steadily, and jinglianwen technology provides data collection and labeling services
景联文科技提供语音数据采集标注服务
树莓派高级开发——“IO口驱动代码的编写“ 包含总线地址、物理_虚拟地址、BCM2835芯片手册知识
数字时代进化论
上位机开发(固件下载软件之详细设计)
Kotlin data flow - flow
16、 IO stream (II)
随机推荐
Network planning common interview knowledge (I)
2022-06-12:在N*N的正方形棋盘中,有N*N个棋子,那么每个格子正好可以拥有一个棋子。 但是现在有些棋子聚集到一个格子上了,比如: 2 0 3 0 1 0 3 0 0 如上的二维数组代表,一
Detailed explanation of scrcpy client code walk through H264 raw stream decoding process
Select all select none JS code implementation
如何使用望友DFM软件进行冷板分析
YOLOv5解析 | 参数与性能指标
Interface oriented programming in C language
How to make a development board from scratch? Illustrated and illustrated, step by step operation for you to see.
Brief introduction to basic usage of echart
Error in downloading opencv from pip
杭州证券开户是安全的吗?
在 localStorage 中上传和检索存储图像
Notepad++ settings delete current line shortcut
【腾讯阿里最全面试题集锦】(四面:3轮技术+1轮HR)
基于FPGA的ds18b20温度传感器使用
树莓派高级开发——“IO口驱动代码的编写“ 包含总线地址、物理_虚拟地址、BCM2835芯片手册知识
The causes of font and style enlargement when the applet is horizontal have been solved
[kernel] two methods of driver compilation: compiling into modules and compiling into the kernel (using miscellaneous device driver templates)
Recently, the popular social e-commerce marketing model, blind box e-commerce, how beautiful every second is accurately drained
Glide usage notes