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