USACO 2015 February Contest Gold T1: Cow Hopscotch

本文介绍了一种解决跳格子游戏问题的动态规划算法,利用线段树进行区间查询和单点修改,实现对网格中不同路径数量的高效计算。

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

题目大意

就像人类喜欢跳格子游戏一样,FJ的奶牛们发明了一种新的跳格子游戏。虽然这种接近一吨的笨拙的动物玩跳格子游戏几乎总是不愉快地结束,但是这并没有阻止奶牛们在每天下午参加跳格子游戏

游戏在一个R*C (2 <= R <= 750, 2 <= C <= 750)的网格上进行,每个格子有一个取值在1-k之间的整数标号,奶牛开始在左上角的格子,目的是通过若干次跳跃后到达右下角的格子,当且仅当格子A和格子B满足如下条件时能从格子A跳到格子B:

1.B格子在A格子的严格右方(B的列号严格大于A的列号)

2.B格子在A格子的严格下方(B的行号严格大于A的行号)

3.B格子的标号和A格子的标号不同

请你帮助奶牛计算出从左上角的格子到右下角的格子一共有多少种不同的方案。

题目分析

观察条件1,2 ,可以得出只有一个点左上方的点才可以更新该点答案。考虑DP, 容易得出DP转移方程为 dp[i][j∑x<i,y<i,a[x][y]!=a[i][j] (a数组为标号)。

 

改写此方程,变为​ dp[i][j∑(x<i,y<i)a[x][y]  -   ∑(x<i,y<i,a[x][y]==a[i][j])a[x][y]。前面的明显可以用前缀和维护,考虑如何维护后面的这个式子。

 

不难看出我们需要单点修改,区间查询。使用线段树维护 当前行 的 上面几行中 标号与当前点(i,j)相同的点的dp值的和。

显然,用一颗线段树无法支持多种标号,所以我们开k颗线段树来维护。
考虑到空间可能不足,这里使用动态开点线段树。

总复杂度为 O(R*C log C) (常数略大)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 
 5 const int MAXN=755;
 6 const ll Mod=1e9+7;
 7 
 8 struct Tree_Node{
 9     int ls,rs;
10     ll sum;
11 }t[MAXN*MAXN<<4];
12 int tot;
13 
14 int n,m,kk;
15 int a[MAXN][MAXN];
16 ll sum[MAXN],f[MAXN][MAXN];
17 
18 inline void Update(int &o,int l,int r,int x,ll v){
19     if(!o) o=++tot;
20     if(l==r){
21         t[o].sum=(t[o].sum+v)%Mod;
22         return;
23     }
24     int mid=(l+r)>>1;
25     if(x<=mid) Update(t[o].ls,l,mid,x,v);
26     else Update(t[o].rs,mid+1,r,x,v);
27     t[o].sum=(t[t[o].ls].sum+t[t[o].rs].sum)%Mod; 
28 }
29 inline ll Query(int k,int l,int r,int x,int y){
30     if(!k) return 0;
31     if(x<=l&&r<=y) return t[k].sum;
32     int mid=(l+r)>>1;
33     ll res=0;
34     if(x<=mid) res+=Query(t[k].ls,l,mid,x,y);
35     if(y>mid) res+=Query(t[k].rs,mid+1,r,x,y);
36     return res%Mod; 
37 }
38 int main(){
39     scanf("%d%d%d",&n,&m,&kk);
40     tot=kk;
41     for(int i=1;i<=n;++i)
42         for(int j=1;j<=m;++j)
43             scanf("%d",&a[i][j]);
44     for(int i=1;i<m;++i)
45         sum[i]=1;
46     f[1][1]=1;
47     Update(a[1][1],1,m,1,f[1][1]);
48     for(int i=2;i<=n;++i){
49         for(int j=2;j<=m;++j){
50             f[i][j]=(sum[j-1]-Query(a[i][j],1,m,1,j-1)+Mod)%Mod;
51         }
52         ll tmp=0;
53         for(int j=2;j<=m;++j){
54             tmp=(tmp+f[i][j])%Mod;
55             sum[j]=(sum[j]+tmp)%Mod;
56             Update(a[i][j],1,m,j,f[i][j]);
57         }
58     }
59     printf("%lld\n",f[n][m]);
60     return 0;
61 } 

 

转载于:https://www.cnblogs.com/LI-dox/p/11213942.html

开发板推荐:天空星STM32F407VET6开发板

超高性价比 STM32主控 | 超高主频 | 一板兼容百芯 | 比赛神器 | 沉金彩色丝印

源码直接下载地址: https://pan.quark.cn/s/a4b39357ea24 USB 眼图检测手段 本资源主要阐述了运用示波器检测 USB 眼图以及时序的检测手段,意在辅助测试工程师独立实施检测。以下是该检测手段的详细知识要点: 一、检测所需仪器设备 * 一台泰克 MSO 70404C 示波器,配备 1 条 P7340A(差分式)和 1 条 P7240(单端式)探针 * 一个 USB 检测夹具(泰克提供) * 三条 USB 线缆,其中 2 条为 A 口转 B 口型的 USB 线缆,另外 1 条为标准的 micro USB 数据线缆 * 一台个人电脑(建议使用笔记本电脑),预装 XHCI HSETT 检测软件 二、USB 眼图检测流程 1. 将差分探针连接至示波器的 CH1 通道,然后将差分探针的另一端连接至 USB 检测夹具上 J310 接口的中间两个引脚(留意正负极的连接)。 2. 通过 2 条 USB 线缆(A 口转 B 口型)将夹具上的 J35 和 J37 接口分别接入笔记本电脑的两个 USB 接口,夹具上的 J35 为供电接口,J37 为数据传输接口。 3. 使用 micro USB 线缆将夹具上的 J34 位置的 A 型 USB 接口与手机相连接,确保手机设置中已开启 USB 调试功能。 4. 将夹具上的单刀双掷开关(S6),调整至下方位置(INIT 红灯点亮)。 5. 检测线路的连接方式如图 1 所示。 6. 启动电脑上的 XHCI HSETT 软件后,点击 TEST 按钮进行操作,若手机与电脑均通过 USB 线缆正常连接至夹具,select device 框中将显示识别到的手机设备。 7. 在 Device Co...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值