zoukankan      html  css  js  c++  java
  • hdu3722Card Game(KM最大带权匹配)

    题目请戳这里

    题目大意:给n个字符串,再给一个n的排列:p1,p2....pn。然后将第i个字符串贴到第pi个字符串后面,然后形成一个环。pi的首字符和第i个字符串的末尾字符就相邻,如果这2个字符相等,各自再向内延伸一个位置,知道这个环首尾字符不等为止。延伸的位置为该环的得分(如果pi == i,得分为0),对于每个排列,有n个这样的环,求得分和最大为多少。

    题目分析:最大带权匹配!!以为是个字符串的题目,就没仔细看。。。

    建图直接跑模版。。。

    详情请见代码:

    #include <iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 205;
    const int M = 1005;
    const int inf = 0x3f3f3f3f;
    char s[N][M];
    int n;
    int lx[N],ly[N],w[N][N];
    bool cx[N],cy[N];
    int match[N];
    int slack;
    int getw(int x,int y)
    {
        int i,j;
        i = strlen(s[x]) - 1;
        j = 0;
        int lenj = strlen(s[y]) - 1;
        int ret = 0;
        while(i >= 0 && j <= lenj && s[x][i] == s[y][j])
            i --,j ++,ret ++;
        return ret;
    }
    void predeal()
    {
        int i,j;
        for(i = 1;i <= n;i ++)
        {
            for(j = 1;j <= n;j ++)
                if(i == j)
                    w[i][j] = 0;
                else
                    w[i][j] = getw(i,j);
        }
    }
    bool path(int u)
    {
        cx[u] = true;
        for(int v = 1;v <= n;v ++)
        {
            if(cy[v] == false)
            {
                int t = lx[u] + ly[v] - w[u][v];
                if(t)
                {
                    if(slack > t)
                        slack = t;
                }
                else
                {
                    cy[v] = true;
                    if(match[v] == -1 || path(match[v]))
                    {
                        match[v] = u;
                        return true;
                    }
                }
            }
        }
        return false;
    }
    void KM()
    {
        int ans = 0;
        int i,j;
        for(i = 1;i <= n;i ++)
        {
            lx[i] = -inf;
            ly[i] = 0;
            for(j = 1;j <= n;j ++)
                if(lx[i] < w[i][j])
                    lx[i] = w[i][j];
        }
        memset(match,-1,sizeof(match));
        for(i = 1;i <= n;i ++)
        {
            while(1)
            {
                memset(cx,false,sizeof(cx));
                memset(cy,false,sizeof(cy));
                slack = inf;
                if(path(i))
                    break;
                for(j = 1;j <= n;j ++)
                {
                    if(cx[j])
                        lx[j] -= slack;
                    if(cy[j])
                        ly[j] += slack;
                }
            }
        }
        for(i = 1;i <= n;i ++)
            ans += w[match[i]][i];
        printf("%d
    ",ans);
    }
    int main()
    {
        while(scanf("%d",&n) != EOF)
        {
            for(int i = 1;i <= n;i ++)
                scanf("%s",s[i]);
            predeal();
            KM();
        }
        return 0;
    }


  • 相关阅读:
    netCore3.1项目搭建过程记录-省的每次都傻乎乎的不知道应该先干啥
    探究 position-sticky 失效问题
    协议的设计一般采用结构体进行数据打包,在协议设计的结构体中能不能使用指针 ?
    ROS pluginlib
    ROS NodeHandle命令空间问题
    ROS 常见命令
    ROS ros::spin() 和 ros::spineOnce区别
    PPM图像文件格式
    Qtcreator for visual studio版本调试问题
    Install Typora For Linux
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3358032.html
Copyright © 2011-2022 走看看