2012 Multi-University Training Contest 3[hdu4320~4330]

 hdu4222 candy

 http://acm.hdu.edu.cn/showproblem.php?pid=4322

費用流 看題解構圖過的, 同時利用了邊的費用和流量 題解這裏,

【題目大意】

有N顆糖果和M個小孩,老師現在要把這N顆糖分給這M個小孩。每個小孩i對每顆糖j都有一個偏愛度Aij,如果他喜歡這顆糖,Aij = k,否則Aij = 1。小孩i覺得高興當且僅當ΣCij×Aij >= Bi,j=1,2,…,N,若他分得了糖j,Cij = 1,否則Cij = 0。問能否合理分配這N顆糖,使得每個小孩都覺得高興。

【建模方法】

(最大費用最大流)

         本題有一個突破點就是:他喜歡這顆糖,Aij = k,否則Aij = 1,關鍵在於如果他不喜歡這個糖分給他一樣可以獲得1點的歡樂值。也就是說如果之前分配了的糖給了小孩一定的歡樂值,不夠bi,可以直接用隨意的糖去填滿。

首先我們要求歡喜值>=bi,是否可以認爲當我獲得歡喜值爲bi後,多餘歡喜值對這個結果的滿足是沒有貢獻的。也就是說,你可以用一個容量來控制分配糖對小孩歡喜值的控制,讓獲得歡喜值最多爲bi。如果不夠,最後用一些1的糖來填滿。

而這個容量就是bi/c,獲取貢獻爲k,bi%c(>1)的也是可以用一個能讓這個小孩歡喜的糖來貢獻,但是其費用只爲bi%c。

對於小孩來說,最大費用最大流後,糖分配的貢獻值爲最大費用,剩餘糖就是(n-最大流),然後用這些糖去填不滿的,只要滿足總和大於Σbj。就可以分配了。

具體建模方案1:

(s,i,1,0);

(i,j,1,0);

(j,t,bj/k,k);

If(bj%k>1)

(j,t,1,bj%k)

Ans = 費用 + N – 最大流 >= Σbj  則滿足要求

 

 

 hdu4223 BKTree 編輯距離

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <map>
#include <vector>
#include <string>
#include <algorithm>

const double pi=cos(-1.);
const double eps=10e-6;
const double eps1=10e-10;
const int inf=0x7fffffff;
const long long infl=1ll<<62;

///******macro defination******///
#define cas(a) int a; scanf("%d", &a); while (a--)
#define cas1(x, a) int a; scanf("%d", &a); for (int x=1; x<=a; ++x)
#define int(a) int a; scanf("%d", &a)
#define char(a) char a; scanf("%c", &a)
#define strr(a, x) char a[x]; scanf("%s", &a)
#define clean0(a) memset (a, 0, sizeof(a));
#define clean(a, x) memset (a, x, sizeof(a));
#define copy(a, b) memcpy(a, b, sizeof(a));
#define up(x,a) for(int x=0; x<a; ++x)
#define down(x,a) for(int x=a-1; x>=0; --x)
#define up1(x,a) for (int x=1; x<=a; ++x)

#define debug(a) printf("here is %d!!!\n", a);
///*** mathmatics ***///
#define sqr(x) (x)*(x)
#define abs(x) (x)>0?(x):(-(x))
#define zero(x) (x)<eps && (x)>eps
///******   by Geners   ******///
typedef long long ll;
typedef unsigned int UI;

using namespace std;

const int maxn=1555;
struct BKTree{
    char str[15];
    int son[25];
}node[maxn];
int idx;
int Levenshtein(char*, char*);

void initBK(int r, char* v)
{
    copy(node[r].str, v);
    clean(node[r].son, -1);
}

void insert(int r, char* str)
{
    int dist=Levenshtein(node[r].str, str);
    if(dist)
    {
        if(node[r].son[dist]==-1)
        {
            initBK(idx, str);
            node[r].son[dist]=idx++;
        }
        else insert(node[r].son[dist], str);
    }
}

int find(int r, char *str, int d)
{
    if(r==-1)return 0;
    int dist=Levenshtein(node[r].str, str);
    //printf("%d r=%d %s %s\n", dist, r, str, node[r].str);
    int ret=(dist<=d);
    for (int i=max(1, dist-d); i<=dist+d; ++i)
    {
        ret+=find(node[r].son[i], str, d);
    }
    return ret;
}

int Levenshtein(char *s1, char *s2)
{
    int dp[20][20];
    int l1=strlen(s1), l2=strlen(s2);
    for (int i=0; i<=l1; ++i)dp[i][0]=i;
    for (int i=0; i<=l2; ++i)dp[0][i]=i;
    for (int j=0; s1[j]; ++j)
    {
        for (int k=0; s2[k]; ++k)
        {
            dp[j+1][k+1]=min(dp[j][k+1]+1,dp[j+1][k]+1);
            dp[j+1][k+1]=min(dp[j+1][k+1], dp[j][k]+(s1[j]!=s2[k]));
        }
    }
    //printf("%d =d(%s %s)\n", dp[l1][l2], s1, s2);
    return dp[l1][l2];
}




int main()
{
    //freopen("1004.in", "r", stdin);
    //freopen("1004a.out", "w", stdout);
    int cas; scanf("%d", &cas);
    for (int I=1; I<=cas; ++I)
    {
        int n, m; scanf("%d%d", &n, &m);
        char str[20];
        idx=0;
        scanf("%s", str); initBK(idx++, str);
        for (int i=1; i<n; ++i)
        {
            scanf("%s", str); insert(0, str);
        }
        printf("Case #%d:\n", I);
        up(p, m)
        {
            char ss[20]; int a; scanf("%s%d", ss, &a);
            printf("%d\n", find(0, ss, a));
        }
    }
    return 0;
}
/*
2
5 2
656
67
9313
1178
38
87 1
9509 1

5 2
656
67
9313
1178
38
87 1
9319 1

*/



 

hdu 4328 cut the cake

http://acm.hdu.edu.cn/showproblem.php?pid=4328

O(n^2)求最大01矩陣周長

原型題求面積 hdu1505 沒看懂題解的方法, 只知道這個方法是O(N^2)的 ,而且能ac.囧

int rectangle(int m)
{
    int res=0;
    for (int i=0; i<maxn; ++i)l[i]=r[i]=i;
    for (int i=0; i<m; ++i)
        while (l[i]-1>=0 && h[l[i]-1]>=h[i])l[i]=l[l[i]-1];
    for (int i=m-1; i>=0; --i)
        while (r[i]+1<m && h[r[i]+1]>=h[i])r[i]=r[r[i]+1];

    for (int i=0; i<m; ++i)
        if(h[i])res=max(res, h[i]+r[i]-l[i]+1);
        //,printf("%d %d %d \n", h[i], l[i], r[i]);
    return res<<1;
}

int square(int n, int m)
{
    for (int i=0; i<m; ++i)dp[0][i]=1;
    for (int i=0; i<n; ++i)dp[i][0]=1;

    for (int i=1; i<n; ++i)
    {
        for (int j=1; j<m; ++j)
        {
            if(imap[i][j]!=imap[i-1][j] && imap[i][j]!=imap[i][j-1])
            {
                int limit=min(dp[i][j-1], dp[i-1][j]);
                dp[i][j]=limit+(imap[i-limit][j-limit]==imap[i][j]);
            }
            else dp[i][j]=1;
        }
    }
    int res=0;
    for (int i=0; i<n; ++i) for (int j=0; j<m; ++j) res=max(res, dp[i][j]);
    return res<<2;
}

int main ()
{
//    freopen("1009.in", "r", stdin);
//    freopen("1009a.out", "w", stdout);
    int cas; scanf("%d", &cas);
    for (int I=1; I<=cas; ++I)
    {
        int n, m; scanf("%d%d", &n, &m);
        char str[maxn];
        for (int i=0; i<n; ++i)
        {
            scanf("%s", str);
            for (int j=0; j<m; ++j)
            {
                imap[i][j]=(str[j]=='B');
            }
        }
        int tmp=square(n, m);
        //printf("%d\n", tmp);
        clean(h, 0);
        for (int i=0; i<n; ++i)
        {
            for (int j=0; j<m; ++j)
            {
                if(imap[i][j])h[j]++;
                else h[j]=0;
            }
            tmp=max(rectangle(m), tmp);
            //printf("Case #%d: %d in %d\n", I, rectangle(m), i);
        }
        clean(h, 0);
        for (int i=0; i<n; ++i)
        {
            for (int j=0; j<m; ++j)
            {
                if(imap[i][j])h[j]=0;
                else h[j]++;
            }
            tmp=max(rectangle(m), tmp);
        }
        printf("Case #%d: %d\n", I, tmp);
    }
    return 0;
}


 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章