zoukankan      html  css  js  c++  java
  • POJ 1692 Crossed Matchings dp[][] 比较有意思的dp

    http://poj.org/problem?id=1692

    这题看完题后就觉得我肯定不会的了,但是题解却很好理解。- - ,做题阴影吗

    所以我还是需要多思考。

    题目是给定两个数组,要求找出最大匹配数量。

    匹配规则是:

    a[i] ==b[j],而且需要产生交叉,而且没对数只能匹配一次。

    一开始的时候我被交叉吓到了,怎么判断交叉啊?

    分析:

    对于a[]的第i个数,b数组的第j个数,假设a[i] != b[j] 如果它能产生匹配,那么就需要,

    对于a[i]这个数字,在b[]的前j - 1个找到和他数字相等的,

    对于b[j]这个数字,在a[]的前i - 1个数中找到一个数字,和b[j]相等,

    这个时候,他们不仅能匹配,而且还是合法了,就是交叉了。所以在这个状态转移过来就好。

    所以设dp[i][j]表示a[]的前i个数,b[]的前j个数。能匹配的最大数量。

    dp[i][j] = max(dp[i][j], dp[posa - 1][posb - 1] + 2);

    当然,第i个数和第j个数也可以不用来匹配,但是要把答案传递下去,所以开始的时候。

    dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    
    const int maxn = 1e2 + 20;
    int dp[maxn][maxn];
    int a[maxn], b[maxn];
    int toFindPos(int nowPos, int val, int which) {
        if (which == 1) {
            while (nowPos--) {
                if (nowPos == 0) return inf;
                if (a[nowPos] == val) return nowPos;
            }
        } else {
            while(nowPos--) {
                if (nowPos == 0) return inf;
                if (b[nowPos] == val) return nowPos;
            }
        }
        assert(false);
    }
    void work() {
        int lena, lenb;
        cin >> lena >> lenb;
        for (int i = 1; i <= lena; ++i) cin >> a[i];
        for (int i = 1; i <= lenb; ++i) cin >> b[i];
        memset(dp, 0, sizeof dp);
        for (int i = 1; i <= lena; ++i) {
            for (int j = 1; j <= lenb; ++j) {
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
                if (a[i] == b[j]) continue;
                int posA = toFindPos(i, b[j], 1);
                int posB = toFindPos(j, a[i], 2);
                if (posA == inf || posB == inf) continue;
                dp[i][j] = max(dp[i][j], dp[posA - 1][posB - 1] + 2);
            }
        }
        cout << dp[lena][lenb] << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        int t;
        cin >> t;
        while (t--) work();
        return 0;
    }
    View Code
  • 相关阅读:
    团队二阶段冲刺个人工作总结9
    团队二阶段冲刺个人工作总结8
    团队二阶段冲刺个人工作总结7
    团队二阶段冲刺个人工作总结6
    PSP总结报告
    第十三周例行报告
    对团队成员公开感谢博客
    附加作业 软件工程原则的应用实例分析
    第十二周例行报告
    第十一周例行报告
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6519543.html
Copyright © 2011-2022 走看看