田忌赛马
这道题遇到太多次了,受不了了,记录一下。
题目描述
给定两个只包含数字的数组a,b,调整数组 a 里面的数字的顺序,使得尽可能多的a[i] > b[i]。
数组a和b中的数字各不相同。
输出所有可以达到最优结果的a数组的结果。
输入描述
输入的第一行是数组 a 中的数字,其中只包含数字,每两个数字之间相隔一个空格,a数组大小不超过10。
输入的第二行是数组 b 中的数字,其中只包含数字,每两个数字之间相隔一个空格,b数组大小不超过10。
输出描述
输出所有可以达到最优结果的 a 数组的数量。
代码
// 题目描述
// 给定两个只包含数字的数组a,b,调整数组 a 里面的数字的顺序,使得尽可能多的a[i] > b[i]。
// 数组a和b中的数字各不相同。
// 输出所有可以达到最优结果的a数组的结果。
// 输入描述
// 输入的第一行是数组 a 中的数字,其中只包含数字,每两个数字之间相隔一个空格,a数组大小不超过10。
// 输入的第二行是数组 b 中的数字,其中只包含数字,每两个数字之间相隔一个空格,b数组大小不超过10。
// 输出描述
// 输出所有可以达到最优结果的 a 数组的数量。
// 获取一个数组的全排列
const getFullPermutation = (numList) => {
const res = [];
const track = [];
// 记录已经使用过的数组
const isVisited = [];
const backTrack = (track, used) => {
// 到达尽头
if (track.length === numList.length) {
res.push(track.concat());
return;
}
for (let i = 0; i < numList.length; i++) {
if (used[i]) {
continue;
}
// 做选择
track.push(numList[i]);
used[i] = true;
// 进入下一层决策树
backTrack(track, used);
// 撤销选择
track.pop();
used[i] = false;
}
};
// 开始回溯
backTrack(track, isVisited);
return res;
};
const getResult = (aList, bList) => {
// 在这个排列模式下,a赢的个数
const countAWin = (aCurList, bCurList) => {
let res = 0;
for (let i = 0; i < aCurList.length; i++) {
if (aCurList[i] > bCurList[i]) {
res++;
}
}
return res;
};
// 获取全排列
const aAllList = getFullPermutation(aList);
console.log('aAllList: ', aAllList);
let res = 0;
// 最优情况数
let maxAWinCase = 0;
for (let i = 0; i < aAllList.length; i++) {
const aWin = countAWin(aAllList[i], bList);
console.log('aWin: ', aWin);
if (aWin > maxAWinCase) {
res = 1;
maxAWinCase = aWin;
} else if (aWin === maxAWinCase) {
res++;
}
}
return res;
};
优化
不记录全排列的路径,在做决策的时候就计算好,省空间复杂度
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
const a = (await readline()).split(" ").map(Number);
const b = (await readline()).split(" ").map(Number);
let maxBiggerCount = 0;
let ans = 0;
function dfs(level, used, biggerCount) {
if (level >= a.length) {
if (biggerCount > maxBiggerCount) {
maxBiggerCount = biggerCount;
ans = 1;
} else if (biggerCount == maxBiggerCount) {
ans += 1;
}
}
for (let i = 0; i < a.length; i++) {
if (used[i]) continue;
used[i] = true;
// biggerCount记录当前全排列中a[level] > b[level]的位置的数量, 此时a[level] == a[i]
dfs(level + 1, used, biggerCount + (a[i] > b[level] ? 1 : 0));
used[i] = false;
}
}
dfs(0, new Array(a.length).fill(false), 0);
console.log(ans);
})();
测试用例和输出结果
aAllList: [
[ 11, 8, 20 ],
[ 11, 20, 8 ],
[ 8, 11, 20 ],
[ 8, 20, 11 ],
[ 20, 11, 8 ],
[ 20, 8, 11 ]
]
aWin: 2
aWin: 3
aWin: 1
aWin: 2
aWin: 2
aWin: 2
res: 1
--------------------
aAllList: [
[ 1, 2, 3 ],
[ 1, 3, 2 ],
[ 2, 1, 3 ],
[ 2, 3, 1 ],
[ 3, 1, 2 ],
[ 3, 2, 1 ]
]
aWin: 0
aWin: 0
aWin: 0
aWin: 0
aWin: 0
aWin: 0
res1: 6
--------------------
aAllList: [
[ 11, 12, 20 ],
[ 11, 20, 12 ],
[ 12, 11, 20 ],
[ 12, 20, 11 ],
[ 20, 11, 12 ],
[ 20, 12, 11 ]
]
aWin: 2
aWin: 3
aWin: 2
aWin: 3
aWin: 2
aWin: 2
res2: 2