1

如果我有以下限制:

values = {$1,$2,$3,$4}  
items = {blue,yellow,green,red}  
weights = {1,2,3,4}  
capacity = 4

我想用代表项目权重的列和代表所选项目数的行填写我的矩阵:

       1      2     3    4    

1     $1     $1    $1    $1
      {1}    {1}   {1}   {1}    
2     $1     $1    $3      $3
      {1}    {1}  {1,2}   {1,2}  
3     $1     $1    $3      $3    
      {1}    {1}  {1,2}   {1,2}
4     $1     $1    $3      $3      <--- should be 4?
      {1}    {1}  {1,2}    {1,2}

我期望看到的是一个提供4正确金额的解决方案,但我得到了3. 大括号中的数字{}表示查找项目的基于索引。我的矩阵填充哪里出错了?

4

1 回答 1

1

解决方案是这样的

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

// m[a][b] = NOWAY => There's no way to represent 
// weight `b` with first `a` items
const int NOWAY = -1;
typedef vector<vector<int>> vvi;

const int values[] = {1, 2, 3, 4}; 
const string items[] = {"blue", "yellow", "green", "red"}; 
const int weights[] = {1, 2, 3, 4};
const int capacity = 4;
const int itemcount = 4;

void rec(vvi const & m, int represent, int mx, vvi & sol);

int main() {
    // m[i][j] -- total value
    // i -- items 1..i were taken
    // j -- total weight of those items
    vvi m(itemcount + 1, vector<int>(capacity + 1, NOWAY));

    // No items weight nothing. The other values we're yet to build
    m[0][0] = 0;
    for (int i = 1; i <= itemcount; ++i) {
        m[i] = m[i - 1];
        int w = weights[i - 1];
        // Find new representations
        for (int j = capacity - w; j >= 0; --j) {
            if (m[i][j] != NOWAY) {
                m[i][j + w] = max(m[i][j + w], m[i][j] + values[i - 1]);
            }
        }
    }
    // Output table
    for (int i = 0; i <= itemcount; ++i) {
        for (int j = 0; j <= capacity; ++j)
            m[i][j] == NOWAY ? cout << "x " : cout << m[i][j] << ' ';
        cout << endl;
    }
    cout << endl;
    // Find the index of the best solution (it's always in the last row)
    int mxi = 0;
    for (int i = 1; i <= capacity; ++i)
        if (m.back()[mxi] < m.back()[i])
            mxi = i;
    // Recurse to get all the representations
    vvi solutions;
    rec(m, mxi, itemcount, solutions);
    // Output them
    for (int i = 0, ilen = solutions.size(); i < ilen; ++i) {
        cout << '{';
        bool f = true;
        for (int j = 0, jlen = solutions[i].size(); j < jlen; ++j) {
            if (!f) cout << ", ";
            cout << items[solutions[i][j]];
            f = false;
        }
        cout << "}" << endl;
    }
}

vector<int> path;
void rec(vvi const & m, int represent, int mx, vvi & sol) {
    if (represent == 0) {
        sol.push_back(path);
        return;
    }
    if (mx <= 0) return;
    for (int i = mx - 1; i >= 0; --i) {
        if (represent < weights[i])
            continue;
        if (m.back()[represent - weights[i]] == m.back()[represent] - values[i]) {
            path.push_back(i);
            rec(m, represent - weights[i], i, sol);
            path.pop_back();
        }
    }
}

它返回

0 x x x x
0 1 x x x
0 1 2 3 x
0 1 2 3 4
0 1 2 3 4

{red}
{blue, green}

(顺便说一下,考虑在USACOTopcoder进行培训。)

于 2013-10-23T14:09:41.397 回答