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;
}