为什么MCARDS需要进行预演

时间:2014-06-13 05:10:23

标签: c++ algorithm lis

我试图在http://www.spoj.com/problems/MCARDS/

上的spoj上解决MCARDS问题

我知道它涉及增长最快的次级逻辑,但经过多次尝试后我没有找到这个问题的解决方案,所以我寻找解决方案 我找到了以下解决方案:

int go (vector < int > &v) {
  int ans = 1;
    int n = v.size();
    vector < int > d(n, 1);
    for(int i = 1; i < n; ++i) {
        int mmax = -1;
        for(int j = 0; j < i; ++j) {
            if(v[j] < v[i] && (mmax == -1 || d[mmax] < d[j])) {
                mmax = j;
            }
        }
        if(mmax != -1) 
            d[i] += d[mmax];
        ans = max(ans, d[i]);
    }
    return ans;
}

int main () {
    int test_case;
#ifndef ONLINE_JUDGE
  IN("/home/tigran/Desktop/Debug/input.txt");
  OUT("/home/tigran/Desktop/Debug/output.txt");
  scanf("%d", &test_case);
#else
  test_case = 1;
#endif
    while(test_case--) {
        int c, n;
        scanf("%d%d", &c, &n);
        int t = n * c;
        vector < int > colors(t), values(t);
        for(int i = 0; i < t; ++i) {
            scanf("%d%d", &colors[i], &values[i]);
        }
        vector < int > ind;
        for(int i = 0; i < c; ++i) {
            ind.push_back(i);
        }
        int mmin = IINF;
        vector < int > v(t);
        do {
            int cnt = 0;
            for(int i = 0; i < c; ++i) {
                for(int j = 0; j < n; ++j) {
                    mat[ind[i]][j] = cnt++;
                }
            }
            for(int i = 0; i < t; ++i) {
                v[i] = mat[colors[i] - 1][values[i] - 1];
            }
            mmin = min(mmin, t - go(v));
        }while(next_permutation(ind.begin(), ind.end()));
        printf("%d\n", mmin);
    }
    return 0;
}

上述解决方案中排列背后的逻辑是什么?

提前致谢

1 个答案:

答案 0 :(得分:2)

这个问题是试图找到最便宜的移动卡片方式,以使它们进入正确的顺序。

置换

假设我们有红色,绿色和蓝色卡片,编号为1到4。

所有相同的颜色必须在一起,并且在每个组内,必须对数字进行排序。

因此有3个!= 3 * 2 * 1 = 6个可能正确的最终订单:

R1 R2 R3 R4 B1 B2 B3 B4 G1 G2 G3 G4  (RBG)
R1 R2 R3 R4 G1 G2 G3 G4 B1 B2 B3 B4  (RGB)
B1 B2 B3 B4 R1 R2 R3 R4 G1 G2 G3 G4  (BRG)
G1 G2 G3 G4 R1 R2 R3 R4 B1 B2 B3 B4  (GRB)
B1 B2 B3 B4 G1 G2 G3 G4 R1 R2 R3 R4  (BGR)
G1 G2 G3 G4 B1 B2 B3 B4 R1 R2 R3 R4  (GBR)

每个订单都由颜色的排列决定(括号中所示)。

此解决方案通过迭代每种颜色的排列来工作。

对于每个排列,它计算每个卡对于给定排列的正确位置。函数go用于计算将v置于排序顺序的最小移动次数。

例如,如果我们选择了排列(RGB),并且这些卡最初是按顺序排列的:

R1 R2 R3 R4 G1 G2 G3 G4 B1 B2 B4 B3

然后v将被计算为

0  1  2  3  4  5  6  7  8  9  11 10

并且go会确定需要一次移动才能对牌进行排序。

计数移动到排序

go函数通过计算v中最长的增加子序列计算出最小数量的移动。

一旦我们找到了LIS,那么我们知道我们必须移动每个不在此子序列中的卡,因此移动的数量是LIS的t长度。 (t是卡的数量)

在我们的例子中,增长最长的子序列是:

     0  1  2  3  4  5  6  7  8  9 10

长度为11,所以答案是12-11 = 1