有趣的算法

動態規劃

參考 關鍵點:找到狀態和狀態轉移方程;把大問題拆分紅小問題再回歸比較html

示例

  1. 如今有硬幣[1, 2, 3, 7, 10]的硬幣,問湊足n元最少須要多少硬幣?
function minimum(total, moneys) {
  const cache = {};
  const getMinimum = (totals) => {
    const list = moneys.map(i => {
      if (totals > i) {
        const nextIndex = totals - i;
        if (!cache[nextIndex]) {
          cache[nextIndex] = getMinimum(nextIndex);
        }
        if (cache[nextIndex]) {
          return [i].concat(cache[nextIndex])
        } else {
          return false
        }
      } else if (totals == i) {
        return [i]
      } else {
        return false
      }
    }).filter(i => !!i)
    if (list.length > 0) {
      return list.sort(function(a,b){return a.length-b.length})[0];
    } else {
      return []
    }
  }
  const back = getMinimum(total);
  return back;
}
minimum(13, [1, 2, 3, 7, 10])
複製代碼
  1. 揹包問題 有n 個物品,它們有各自的重量和價值,現有給定容量的揹包,如何讓揹包裏裝入的物品具備最大的價值總和?
i 1 2 3 4
w(體積) 2 3 4 5
v(價值) 3 4 5 6
function test(total, arr) {
  const unshift = arr.pop();
  console.log(arr, _.cloneDeep(arr));
  let next = [];
  if (arr.length > 0) {
    const bin1 = [unshift].concat(test(total - unshift[0], _.cloneDeep(arr)));
    const bin2 = test(total, _.cloneDeep(arr));
    const bin1W = bin1.map(item => item[0]).concat([0]).reduce(function(prev, curr){return prev + curr});
    const bin2W = bin2.map(item => item[0]).concat([0]).reduce(function(prev, curr){return prev + curr});
    if (bin1W > total && bin2W > total) {
      return []
    } else if (bin1W > total && bin2W <= total) {
      return bin2
    } else if (bin1W <= total && bin2W > total) {
      return bin1
    } else{
      const bin1V = bin1.map(item => item[1]).concat([0]).reduce(function(prev, curr){return prev + curr});
      const bin2V = bin2.map(item => item[1]).concat([0]).reduce(function(prev, curr){return prev + curr});
      return bin1V > bin2V ? bin1 : bin2
    }
  } else {
    if (unshift[0] > total) {
      return []
    } else {
      return [unshift]
    }
  }
}
const res = test(10, [[2, 3], [3, 4], [4, 5], [5, 6]]);
if (res.length <= 0) {
  console.log('無結果');
} else {
  console.log(`能夠裝:${JSON.stringify(res)},價值是:${res.map(item => item[1]).reduce(function(prev, curr){return prev + curr})}`)
}
複製代碼
  1. 平面上有N*M個格子,每一個格子中放着必定數量的蘋果。你從左上角的格子開始, 每一步只能向下走或是向右走,每次走到一個格子上就把格子裏的蘋果收集起來, 這樣下去,你最多能收集到多少個蘋果。
function test(arr) {
  const cache = {};
  const max = function(i, j) {
    console.log(i, j);
    if (i == arr.length - 1 && j == arr[0].length -1 ) {
      return [[i, j, arr[i][j]]]
    } else if (i == arr.length -1 ) {
      return [[i, j, arr[i][j]]].concat(max(i, j + 1));
    } else if (j == arr[0].length -1 ) {
      return [[i, j, arr[i][j]]].concat(max(i + 1, j));
    }
    const key = `${i}-${j}`;
    if (!cache[key]) {
      const rightList = max(i, j + 1);
      const leftList = max(i + 1, j);
      const rightListValue = rightList.map(item => item[2]).reduce(function(prev, curr){
        return prev + curr;
      });
      const leftListValue = leftList.map(item => item[2]).reduce(function(prev, curr){
        return prev + curr;
      });;
      cache[key] = [[i, j, arr[i][j]]].concat(rightListValue > leftListValue ? rightList: leftList);
    }
    return cache[key]
  }
  const list = [[0, 0, arr[0][0]]].concat(max(0, 0));
  console.log(cache, list, list.map(item => item[2]).reduce(function(prev, curr){
        return prev + curr;
      }))
}
test([
  [56, 85, 16, 1, 55, 79],
  [11, 87, 86, 94, 84, 54],
  [15, 94, 17, 11, 13, 97],
  [76, 60, 94, 21, 78, 49],
  [3, 16, 90, 86, 73, 45],
]);
複製代碼
  1. 無向圖G有N個結點,它的邊上帶有正的權重值。 你從結點1開始走,而且一開始的時候你身上帶有M元錢。若是你通過結點i, 那麼你就要花掉S[i]元(能夠把這想象爲收過路費)。若是你沒有足夠的錢, 就不能從那個結點通過。在這樣的限制條件下,找到從結點1到結點N的最短路徑。 或者輸出該路徑不存在。若是存在多條最短路徑,那麼輸出花錢數量最少的那條。 限制:1<N<=100 ; 0<=M<=100 ; 對於每一個i,0<=S[i]<=100。

遺傳算法

遺傳算法(Genetic Algorithm)是模擬達爾文生物進化論的天然選擇和遺傳學機理的生物進化過程的計算模型,是一種經過模擬天然進化過程搜索最優解的方法。 具體而言,它有兩個核心要點:第一是編碼,即須要找到一種合適的方法,將待解決的問題映射爲「基因」編碼,生成多個個體;第二是評估,即須要一種定量的方法給每一個個體打分,評估哪一個個體所對應的方案更接近最佳答案,從而能夠根據這個分數優勝劣汰。算法

示例

蟻羣算法

介紹能夠看下百度百科,裏面仍是講的比較清楚。bash

思想

將蟻羣算法應用於解決優化問題的基本思路爲:用螞蟻的行走路徑表示待優化問題的可行解,整個螞蟻羣體的全部路徑構成待優化問題的解空間。路徑較短的螞蟻釋放的信息素量較多,隨着時間的推動,較短的路徑上累積的信息素濃度逐漸增高,選擇該路徑的螞蟻個數也越來越多。最終,整個螞蟻會在正反饋的做用下集中到最佳的路徑上,此時對應的即是待優化問題的最優解網絡

實現

螞蟻找到最短路徑要歸功於信息素和環境,假設有兩條路可從蟻窩通向食物,開始時兩條路上的螞蟻數量差很少:當螞蟻到達終點以後會當即返回,距離短的路上的螞蟻往返一次時間短,重複頻率快,在單位時間裏往返螞蟻的數目就多,留下的信息素也多,會吸引更多螞蟻過來,會留下更多信息素。而距離長的路正相反,所以愈來愈多的螞蟻彙集到最短路徑上來。post

示例

可應用的問題:旅行商問題、指派問題、Job—shop調度問題、車輛路由問題、圖着色問題和網絡路由問題等 本例實現「車輛路由問題」:優化

複製代碼
相關文章
相關標籤/搜索