BZOJ3939 BSOJ4853 【USACO 2015 FEB GOLD 】cow hopscotch
来源:互联网 发布:oppoa100软件下载 编辑:程序博客网 时间:2024/05/18 14:24
4853 -- 【USACO 2015 FEB GOLD 】cow hopscotch
Description
就像人类喜欢玩“跳房子”的游戏,农民约翰的奶牛已经发明了该游戏的一个变种自己玩。由于笨拙的动物体重近一吨打,牛跳房子几乎总是以灾难告终,但这是没有阻止奶牛几乎每天下午玩这个游戏。
游戏的矩阵共有R*C格(2 <= R <= 750,2 <= C <= 750),其中每一格是个正方形并被标记为一个整数K( 1 < = K <= R * C)。游戏是牛开始在左上角最后向右下角移动到的一个跳跃序列,牛从一个格子只能跳到在他的严格右下方(行列都要大于当前位置)与当前格子权值不同的格子上。请帮助奶牛计算不同可能的有效跳跃序列的数量。
Input
第一行三个整数 R, C, K.
以下R行,每行 C个整数.
Output
输出方案数,由于数太大,请对答案取模 1000000007.
Sample Input
4 4 4
1 1 1 1
1 3 2 1
1 2 4 1
1 1 1 1
Sample Output
5
【分析】动规,CDQ
题意:给你一个n(750)*m(750)的棋盘,每个格子(i,j)都有一种颜色c[i][j],颜色范围是[1,n*m]中的整数,对于一次跳跃A(y1,x1)->B(y2,x2),我们说这次跳跃是合法的,要求必须有:
1,y2>y1
2,x2>x1
3,c[y1][x1]!=c[y2][x2];
我们想要求出从(1,1)经过若干次跳跃之后到达(n,m)的方案数,
首先,我们可以构想一个暴力DP:
用f[i][j]表示从(1,1)到(i,j)的方案数
那么f[i][j]=∑f[u][v],u<i&&v<j&&c[u][v]!=c[i][j]
时间复杂度为O(n^2 m^2),想要通过这题,这还差得远。
思考1,
我们观察到,这道题中,颜色的范围不是1e9,而是5e5。为什么呢?
我们发现,相比较1e9,5e5这个范围的数组是开得下的,于是我们可以做计数处理,有助于我们维护答案。
(ps:如果颜色属于1e9范围,因为颜色种类最多只有n*m,所以其实我们可以离散化)
如果我们用d[x]表示颜色为从(1,1)走到当前处理范围颜色为x的点的方案数,
并用一个大的变量tot统计从(1,1)走到当前处理范围所有点的方案数之和。
那么当我们走到一个颜色为x的点时,就可以直接使用 tot-d[x] 来更新到达这个点的方案数。
这个思想有一定的价值,但是因为题目给出的1,2两个限制条件。
具体要通过什么途径保证d[]中处理的所有点都在它之间呢?
思考2,
区间问题的实现,很多时候我们都要引入整段考虑的思想。
这其实也就是CDQ分治的思想与具体实现。
我们想要更新从(1,1)走到行[l,r]范围格点的方案数。
而line[l,r]每个格子更新的来源,有两方面。
1,line[1,l-1]
2,line[l,r]内部
我们假设在处理[l,r]时,所有line[1,l-1]对line[l,r]的贡献已经生效。
于是现在只需要考虑来自于line[l,r]内部的贡献。
并且定义过程solve(l,r),用于解决[l,r]内部贡献的转移。
具体如何实现?
1,如果l==r,那不会生成任何贡献,直接结束。
2,否则我们设m=(l+r)>>1;
接下来只要依次实现以下3个步骤,这道题就做完了。
(1),solve(l,m);
(2),从[l,m]向[m+1,r]转移贡献;
(3),solve(m+1,r);
于是,关键落在要如何实现(2)上——
此时,我们发现行关系已经是严格的小于关系,只需要使得列关系满足要求。如何使得?
因为问题不是在数轴上,而是在矩形中。
所以目前处理的区间是一个块,行数是[l,r],每行有m列。
我们现在是想要把[l,mid]的状态传递到[mid+1,r]。
发现只需要从左向右一列列枚举。
状态结果的传递在(mid,r])实现,状态来源的累计在[l,mid]实现。
就保证了行与列都是严格小于关系,这道题也就在O(nmlogn)的时间复杂度内解决了。
设f[i][j]表示到(i,j)的方案数,则有
f[i][j]=∑f[x][y](x<i,y<j,a[x][y]!=a[i][j])
=∑f[x][y](x<i,y<j)−∑f[x][y](x<i,y<j,a[x][y]==a[i][j])
CDQ:按列分治处理
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 1010#define MAXM 1010#define ll long long#define INF 1000000000#define MOD 1000000007#define eps 1e-8ll f[MAXN][MAXN],s[MAXN*MAXN];int n,m,k, vis[MAXN*MAXN],T,a[MAXN][MAXN];inline void ck(int x){ if(vis[x]!=T) s[x]=0;//本次第一次统计x颜色,原值清零 vis[x]=T;//设x颜色标志}void CDQ(int l,int r){ if(l==r){ return ; } Int i,j, mid=l+r>>1; CDQ(l,mid);//前半部分 //前半部分对后半部分影响 ll sum=0; T++;//本次是否已访问,T每次不同,这样vis不用每次清零,且用到时才清(快些!!) for(i=2;i<=n;i++){//针对每行 for(j=l;j<=mid;j++){//前半部的列,累加方案数 (sum+=f[i-1][j])%=MOD;//总和,不管颜色 ck(a[i-1][j]); (s[a[i-1][j]]+=f[i-1][j])%=MOD;//统计前半部分合法位置某颜色方案数的和 } for(j=mid+1;j<=r;j++){//后半部的列 ck(a[i][j]); (f[i][j]+=sum-s[a[i][j]]+MOD)%=MOD;//总的减去颜色相等的方案 } } CDQmid+1,r);}int main(){ int i,j; scanf("%d%d%d",&n,&m,&k); f[1][1]=1; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ scanf("%d",&a[i][j]); } } CDQ(1,m); printf("%lld\n",f[n][m]); return 0;}
法2:线段树
考虑暴力递推
f[i][j]=∑f[k][l],k<i且l<j且color[i][j]!=color[k][l]
设F[i][j]表示走到(i,j)这个格子的方案数,那么转移方程就是严格左上的所有格子的F值和减去和他相同颜色的F值和,前者可以直接维护前缀和得出,后者可以对每种颜色建一个动态开点的线段树来维护,时间复杂度O(NMlognm),空间复杂度O(NMlognm)
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define N 751#define M 6000010int mod=1e9+7;using namespace std;int f[N][N],a[N][N],pre[N][N];int rt[N*N],ch[M][2],sum[M],cnt;void addnew(int &y,int l,int r,int v,int w){ if(!y) cnt++,y=cnt; sum[y]=(sum[y]+w)%mod; if(l==r) return; int mid=(l+r)>>1; if(v<=mid) addnew(ch[y][0],l,mid,v,w); else addnew(ch[y][1],mid+1,r,v,w);}int check(int x,int l,int r,int ll,int rr){ if(l==ll&&r==rr) return sum[x]; int mid=(l+r)>>1; if(rr<=mid) return check(ch[x][0],l,mid,ll,rr); else if(ll>mid) return check(ch[x][1],mid+1,r,ll,rr);else return (check(ch[x][0],l,mid,ll,mid)+check(ch[x][1],mid+1,r,mid+1,rr))%mod;}int main(){ int r,c,k; scanf("%d%d%d",&r,&c,&k); int i,j; for(i=1;i<=r;i++) { for(j=1;j<=c;j++) { scanf("%d",&a[i][j]); if(i!=1&&j!=1) f[i][j]=(pre[i-1][j-1]-check(rt[a[i][j]],1,c,1,j-1))%mod; else if(i==1&&j==1) f[i][j]=1; } for(j=1;j<=c;j++) { pre[i][j]=(((pre[i][j-1]+pre[i-1][j])%mod-pre[i-1][j-1])%mod+f[i][j])%mod; addnew(rt[a[i][j]],1,c,j,f[i][j]); } } printf("%d",(f[r][c]+mod)%mod);}
0 0
- BZOJ3939 BSOJ4853 【USACO 2015 FEB GOLD 】cow hopscotch
- bzoj3939 【USACO 2015 FEB GOLD 】cow hopscotch
- BZOJ3939 [Usaco2015 Feb]Cow Hopscotch
- BZOJ3939: [Usaco2015 Feb]Cow Hopscotch
- [BZOJ3939][Usaco2015 Feb]Cow Hopscotch(cdq分治)
- bzoj3939 Cow Hopscotch
- 【POJ3666】【USACO 2008 Feb Gold】 2.Cow Game 动规
- USACO 2015 Feb Gold 检查 (AC自动机+栈)
- BZOJ 3939 [Usaco2015 Feb] Cow Hopscotch
- POJ 3269 USACO FEB GOLD newbarn
- [USACO 2014 Feb Silver && Gold] Roadblock
- USACO 2009 Feb Gold 3.Revamping Trails
- USACO 2011 Feb Gold 1.Cowlphabet(dp)
- [题解] USACO cow hopscotch(牛跳房子)
- 【USACO】2014 Feb Cow Decathlon 全能奶牛
- 【USACO】2002 Feb Cow Cycling 奶牛赛车
- BZOJ 3939 [Usaco2015 Feb]Cow Hopscotch 线段树
- bzoj 3939: [Usaco2015 Feb]Cow Hopscotch (CDQ分治+DP)
- javaWeb之初识Servlet
- C# FileStream复制大文件
- 分享45个Android实例源码
- JDBC基础(JDBCVersion1)
- 【严肃脸】使用caffe实现色情图片的识别
- BZOJ3939 BSOJ4853 【USACO 2015 FEB GOLD 】cow hopscotch
- Markdown学习与集成
- HDU - 1131 Count the Trees
- HDU Fraction 2016中国大学生程序设计竞赛(长春)-重现赛
- 【Codeforces 718C&719E】Sasha and Array【线段树成段更新+矩阵快速幂】
- 关于hibernate中实体类为什么尽量序列化和类似<s:checkboxlist/>标签
- [LeetCode]318. Maximum Product of Word Lengths
- 为什么罗永浩这种人都能做出来锤子手机?
- test