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

来源:互联网 发布:天猫抢购软件神器 编辑:程序博客网 时间:2024/06/05 07:07

 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;}/*25 265667931311783887 19509 15 265667931311783887 19319 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;}


 

 

原创粉丝点击