8.9


POJ 3189 枚举 多重匹配
/*
 题意:N头cow,B个barn 每个barn有容量ci,给出每头cow对这些barn喜爱程度排序的列表
 问如何安排,使所有的牛之间的满意度的最大差最小
 题意比较绕口
 设最满意程度为u,最不满意程度为v  则答案就是u-v了
 可以直接O(B^2)枚举[v,u]
 更快的做法是,如果[v,u]可行,则[v,u+k]肯定可行
 根据这个,用两个指针,如果可行,left++;不行right++
 然后用匈牙利多重匹配做即可
 这种用两个指针枚举的方法有通用性
*/



URAL 1699 ★★★ 建立LCA 细节处理好
/*
 题意:给出一个地图,一些地方可以走
 The ground is constructed in such a way that there is  exactly one way to get from one passable cell to another passable cell without visiting any cell twice.
 表明是一棵树
 然后给出Q个询问,问a到b的最少转的次数
 以'#'建一棵树,预处理LCA
 然后读入查询,找到LCA  再分情况讨论一下cost[]即可
 if LCA(a,b)=a  da=0
 else 考虑LCA(a,b)向上有没转 有的话da=dist[a]-dist[LCA(a,b)]-1 要-1

 R*C<=100000  递归会爆
 要用非递归...
*/
http://www.cppblog.com/Yuan/archive/2010/08/09/122849.html



POJ 1149 构图不错
/*
 题意: 给出m个猪圈,n个顾客。每个顾客有一些钥匙开猪圈的,开了后那些猪可重新分配也行
    顾客要买Bi头猪  顾客走后门就关了就不能再调整猪了  
    猪圈一开始有一些猪,猪圈可容纳无限的猪
    问能卖出去的最大猪的数目

 这道题,我一开始做,构图是正确,一个小地方写错了,搞了我半天了!
 构图如下:
 S向猪圈连边,容量为猪圈猪的数目
 顾客向T连边,容量为顾客要买的数目
 顾客的钥匙对应的猪圈向顾客连边,容量无限
 如果顾客i跟前面的顾客j有共同的钥匙就能连j->i,容量无限
 
 我这样子构图跟网上的有点不一样,不过核心都是差不多吧 
 “若第i个人与他后面的第j个人有同一个猪圈的钥匙,则从i引边到j,容量为无穷大”


 网上详细构图:http://imlazy.ycool.com/post.2059102.html
 他这种构图方法更巧,去掉了猪圈了(猪圈数目较大)  不过对我就难想到
*/


hdu 2888
二维RMQ  用dp[i][j][k1][k2]表示矩形(i,j)  (i+(1<<k1)-1,j+(1<<k2)-1)的最值





8.10


hdu 3485 
求长度为n的不包含101子串串的个数  跟hdu 2604类似

如图,长度为n的合法串,后缀可以是0,001,0011,00111,...
所以dp[n]=dp[n-1]+dp[n-3]+dp[n-4]+...+dp[1]
而dp[n-1]=dp[n-2]+dp[n-4]+...+dp[1]
两式相减,得到dp[n]=2*dp[n-1]-dp[n-2]+dp[n-3]




hdu 3486
/*
 题意:给出n个数,求分成多少段,使得每段的最大值之和>k (末尾不足一段的丢弃)
 二分分成多少段,直接做即可 O(nlogn)
 用线段树会更慢,O(nlognlogn)
*/


hdu 3482
/*
 题意:问满足条件的长度为n的串的个数  条件是每个长度为m的子串的数字要么全不同、要么全相同
 分类讨论
 m=1  1
 m=2  2^n
 m>n (不存在长度为m的子串)   m^n
 m<=n  m!+m (其实,确定了前m个后面的都会确定的,所以m!  再加上全相同)
*/



hdu 3478
/*
 题意:给出一个无向图,一个起点,问是否在某个时候,这个人有可能在所有点都可以出现
     人不能停留在原地
 画一下图就知道,只要存在奇圈,那么奇圈的点就可以任何时刻都出现人
 同时,对于奇圈外的,奇圈可以源源不断地传到奇圈外
 这样肯定存在某个时刻,其他点也可以同时出现人(因为源源不断传出来,所以肯定会波及所有)
*/
http://www.cppblog.com/Yuan/archive/2010/08/11/123005.html




8.11

hdu 3516
/*
 题意:给出n个点,如果满足 xi < xj and yi > yj for all i < j  就可以在点(xi,yj)向点i,j连边
 求把他们连成一棵树的最小代价
 跟矩阵连乘的加括号一样
 dp[i][j]=min{dp[i][k]+dp[k+1][j]+(pt[k+1].x-pt[i].x)+(pt[k].y-pt[j].y)}
 n<1000
 需要四边形不等式  O(n^2)
*/


hdu 3512
/*
    题意:给出上面n个数,下面n个数,求完美匹配的最大边最小。边权定义为两个数相乘。可以负数
    应该有点YY的
    先分一下情况
    同号:大*小  才能使最大那个最小
    异号:小*小  才能使最大那个最小
    一点贪心的思想
    上面的那些正数跟下面的负数匹配
    上面的那些负数跟下面的正数匹配
    这样剩下来的(当然可以没有剩下),肯定是同号的,而且这些数更接近于0

    现在再来看那些 正数*负数 的情况
    刚才提到“小*小  才能使最大那个最小”,而且越小的话越好
    所以上面那些最大的正数跟下面那些最小的负数匹配(顺序匹配,大-大,小-小)
    同理,上面的那些最小的负数跟下面那些最大的正数匹配

    就这样先排序,然后找出各自的0的位置
    再分类一下即可
*/
http://www.cppblog.com/Yuan/archive/2010/08/11/123105.html





8.12

hdu 3481

/*
 题意:问长度为n的bad serial串的个数。bad serial 指每一个长度为m的子串都不是good serial
 (good serial指要么全相同,要么全不同),所以bad serial就是两个以上不同,但不能m个都不同

 dp[i,j](1<=j<m)表示长度为i的串最后j个数字互不相同的串个数(即str[i-j]与末尾这j个数中一个相同)

 考虑dp[i+1,j+1]
 (1)dp[i+1,j+1]+=dp[i,j]*(m-j)   选一个与i及之前j个数字都不同的
 (2)dp[i+1,k]+=dp[i,j]  2<=k<=j  选一个与i之前j个数字某个相同的 str[i+1]=str[i+1-k]
 还有一种特殊的就是dp[i,1],即末尾几个数字都相同的合法串个数
 (3)dp[i+k,1]+=dp[i,j]  (1+k<=m-1, j>1||i==1)
 如果j=1的话有可能一连串都相同导致不合法,要j>1
 特殊的是i=1,j=1就可取,因为1之前没有数字,认为与1不同(跟j>1一样)


 心得:只考虑最后一个字符(第i+1),考虑怎么合法过来的
     dp转移时,由之前的转移过来难写的话,写成从当前扩展到之后的!
     按照题意定义状态,这里要2个以上不同,定义末尾有j个不同(j=1时是特殊情况,即末尾可以几个连续相同)
*/


hdu 3510
/*
 题意:给出n个任务,m台机器  任务间有依赖关系,这些关系构成一棵树  问最短完成时间
 显然完成时间不能少于最深的深度,而每次只能选叶子被机器加工
 这样,每次选深度最深的叶子加工(用PQ)直到完成
 如果不选深度最深的,可能会使时间变长
*/



hdu 3508
/*
 题意:问n内,与n互质的所有数的乘积模n是多少
 打了一些数据,发现只有1和n-1
 当n=1,2,4,p^k,2*p^k时  答案为n-1
*/


hdu 3483
/*
 题意:给出N,x,M 要计算
 N
 ∑(k^x)*(x^k) MOD M
 k=1
        x  
 用到二项式定理,(n+1)^x = ∑C(x,k)n^k  
        k=0
 然后构造矩阵,求和  S(n)表示前n项和
http://www.cppblog.com/Yuan/archive/2010/08/13/123268.html
*/


hdu 3366
/*
 如果已经知道走这些passage的顺序的话,应该可以dp出来的
 但是这里不确定顺序,要选择最优,可以按照P/Q从大到小排序
 遇到匪徒几率Q越小,出去几率P越大,肯定是我们优先考虑的!
 Help Bill to find out the probability that he can escape from this castle if he chose the optimal strategy.

 dp[i][j]表示现在有钱j,在i个passage处,最后能够出去的概率
 dp[n-1,j]=P[n-1]
 dp[i,j]=P[i]+Q[i]*dp[i+1,j-1]+(1-P[i]-Q[i])*dp[i+1,j]   j>0
 dp[i,j]=P[i]+(1-P[i]-Q[i])*dp[i+1,j]   j=0

 概率题期望题,一般都是表示现在离目标的值
 (因为当前接下来的方案确定了,概率也知道了,而当前从前面过来就不确定概率了,其概率跟路径有关)
*/




8.13

zoj 2597
/*
 题意:题目定义一种n位的yellow code  相邻两个数之间要差别至少[n/2]。让你构造出n位的yellow code
 观察发现,n位可以由n-1位复制一遍,然后最后一列再算一下得来
 对最后一列的前n个爆搜即可,后n个是前n个取反
*/

zoj 1619
/*
 题意:n个人n个礼物混乱,问每人取一个,最终m个人取到自己的概率
 直接用错排公式即可  C(n,m)*D[n-m]/n!
 或者dp
 dp[i,j]表示前i个人j个取得自己的概率
 dp[i,j]可以先安置好i-1的,然后再用乘法原理乘起来
 dp[i,j] = dp[i-1,j]*(i-1-j)/i    先把i-1个人安置出j个人取到自己的情况,为使还是j个人,第i个人需跟剩下的i-1-j个人其中一个交换
   + dp[i-1,j-1]*1/i       先把i-1个人安置出j-1个人取到自己的情况,然后第i个人取到自己的概率
   + dp[i-1,j+1]*(j+1)/i  先把i-1个人安置出j+1个人取到自己的情况,然后第i个人跟这j+1个人之一交换

*/


8.14

zoj 2703 被这道题卡了好久,还是wa

8.16
做了下伸展树的
spoj 4487     1470


8.17

cii 2193
/*
 sample:
 ##-(##+###)
 3333333
 用下面的数字去填上面的#使得该式子最大  有多个时输出字典序最小的
 
 首先,去括号
 没有真的去掉,利用括号前的那些正负号来确定每个数字真实的正负号
 为每个数字或者括号这样的整体添加正负号
 如下面的例子  +(-(+a+b)+c)
 这里在最外的括号及a也要有一个正号

 为了转化出上面的式子用一个栈
 1) '(' 如果其前面不是符号,就需要添加一个符号(跟栈顶一样) push(top)
 2) '(' pop
 3) '±' push(op^top)  这里把负号当成1
 4) '#' 如果其前面不是符号就需要添加一个符号(跟栈顶一样) push(top)
    然后连读... 存起这个数  再pop
 
 正数存在positive 负数存在negative

 现在就来贪心  先将digit排序
 对于正数,每次将digit里最大的数赋值给positive里长度最大的,或长度相同靠后的
 对于负数,每次将digit里最小的数赋值给negative里长度最大的,或长度相同靠前的
 
 可用一个堆来实现,取出后再放进去(这时长度少1了)

*/