HDU 3722 Card Game KM水题

来源:互联网 发布:流量挂机赚钱软件 编辑:程序博客网 时间:2024/05/18 22:40

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3722

大意就是给n个字符串,然后对于任意两个字符串进行匹配,第一个倒序,第二个正序,找它们的最长公共前缀长度,就是它们的分数,自己和自己匹配分数为0,然后把这些字符串组成一些圈,求能得到的最大分数

思路:预先处理出任意的两个字符串的分数,然后KM。。。

#include <iostream>#include <string>#include <cstdio>#include <algorithm>#include <cstring>#include <cctype>#include <vector>using namespace std;const int N = 210;const int INF = 0x3f3f3f3f;int nx, ny;int lx[N], ly[N], match[N], slack[N];bool visx[N], visy[N];int s[N][N];char str[N][1010];bool hungary(int v){    visx[v] = true;    for(int i = 0; i < ny; i++)    {        if(visy[i]) continue;        if(lx[v] + ly[i] == s[v][i])        {            visy[i] = true;            if(match[i] == -1 || hungary(match[i]))            {                match[i] = v;                return true;            }        }        else slack[i] = min(slack[i], lx[v] + ly[i] - s[v][i]);    }    return false;}void km(){    memset(match, -1, sizeof match);    memset(ly, 0, sizeof ly);    memset(lx, 0, sizeof lx);    for(int i = 0; i < nx; i++)        for(int j = 0; j < ny; j++)            lx[i] = max(lx[i], s[i][j]);    for(int i = 0; i < nx; i++)    {        memset(slack, 0x3f, sizeof slack);        while(true)        {            memset(visx, 0, sizeof visx);            memset(visy, 0, sizeof visy);            if(hungary(i)) break;            else            {                int tmp = INF;                for(int j = 0; j < ny; j++)                    if(!visy[j]) tmp = min(tmp, slack[j]);                for(int j = 0; j < nx; j++)                    if(visx[j]) lx[j] -= tmp;                for(int j = 0; j < ny; j++)                    if(visy[j]) ly[j] += tmp;                    else slack[j] -= tmp;            }        }    }}int judge(char s1[], char s2[]){    int res = 0;    for(int i = strlen(s1) - 1, j = 0; s1[i] && s2[j]; i--, j++)        if(s1[i] != s2[j]) return res;        else res++;    return res;}int main(){    int n;    while(~ scanf("%d", &n))    {        for(int i = 0; i < n; i++)            scanf(" %s", str[i]);        for(int i = 0; i < n; i++)            for(int j = 0; j < n; j++)                if(i == j) s[i][j] = 0;                else s[i][j] = judge(str[i], str[j]);        nx = ny = n;        km();        int res = 0;        for(int i = 0; i < n; i++)            res += s[match[i]][i];        printf("%d\n", res);    }    return 0;}


0 0
原创粉丝点击