2014年百度之星程序设计大赛 - 初赛(第二轮)Chess
题目描述:小度和小良最近又迷上了下棋。棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M)。在他们的规则中,“王”在棋盘上的走法遵循十字路线。也就是说,如果“王”当前在(x,y)点,小度在下一步可以移动到(x+1, y), (x-1, y), (x, y+1), (x, y-1), (x+2, y), (x-2, y), (x, y+2), (x, y-2) 这八个点中的任意一个。

小度觉得每次都是小良赢,没意思。为了难倒小良,他想出了这样一个问题:如果一开始“王”在(x0,y0)点,小良对“王”连续移动恰好K步,一共可以有多少种不同的移动方案?两种方案相同,当且仅当它们的K次移动全部都是一样的。也就是说,先向左再向右移动,和先向右再向左移动被认为是不同的方案。
输入:输入包括多组数据。输入数据的第一行是一个整数T(T≤10),表示测试数据的组数。每组测试数据只包括一行,为五个整数N,M,K,x0,y0。(1≤N,M,K≤1000,1≤x0≤N,1≤y0≤M)
输出:对于第k组数据,第一行输出Case #k:,第二行输出所求的方案数。由于答案可能非常大,你只需要输出结果对9999991取模之后的值即可。
这个题目,开始做的时候挺纠结,最直接的思路就是从王的起始点一步一步的计算到达其它位置的方案数,不过复杂度太高,会超时,下面先说下自己开始的思路,然后通过这个思路改进来解决这道题目。定义一个数组dp[x][i][j](0<=x<=k,1<=i<=n,1<=j<=m),表示经过x步到达位置(i,j)的方案数,move[8][2] = {{1,0},{-1,0},{0,1},{0,-1},{2,0},{-2,0},{0,2},{0,-2}},那么dp[x+1][i][j] = sumo(dp[x][i - move[o][0]][j - move[o][1]])(0<=o<8),sumo表示以o变化来累加,最终只要将dp[k][i][j](1<=i<=n,1<=j<=m)都加就是总的方案数了。但由于k,n,m的最大值都为1000,所以直接定义dp[1001][1001][1001]占用的存储空间过大,再看前面的推导式子dp[x+1][i][j]只与dp[x][i'][j']有关,所以可以定义滚动数组dp[2][1001][1001]来节约空间。可以很容易的看出这个思路的复杂度是O(k*n*m),显然这个复杂度不能满足题目要求。
可不可以根据上面思路优化下呢,最终我们需要计算dp[k][i][j](1<=i<=n,1<=j<=m)的和,前面的思路是一步一步经过k步来推导出dp[k][i][j],可以不可以用起来的方法求dp[k][i][j]呢?考虑到这是一个矩阵,移动的方向只能是行或者列,所有很自然想到行列步数的组合来求dp[k][i][j],即dp[k][i][j] = sumt(C[k][t] * dp1[t][i] * dp2[k - t][j]),dp1[t][i]表示在列方向经过t步到达i,dp2[k - t][j]表示在行方向经过k - t步到达j,C[k][t]是组合数。计算dp1和dp2可以通过前面一步一步推的思路求解,只是维度变成一维的了,复杂度分别为O(k * n), O(k * m)。求最终结果也是将所有dp[k][i][j](1<=i<=n,1<=j<=m)加起来,这个计算式和前面不同的是由于行列式独立的,所以最终的ans = sumi(sumj(sumt(C[k][t] * dp1[t][i] * dp2[k - t][j]))) = sumt(C[k][t] * sumi(dp1[t][i]) * sumj(dp2[k - t][j])),C[k][t]可以根据组合数的性质C[k][t] = C[k - 1][t] + C[k - 1][t - 1]求得,所以这个思路的算法复杂度为O(max( k * n, k * m, k^2)),可以满足题目要求了。
具体代码如下:
#include <iostream>
#include <cstring>
using namespace std; int n, m, k, x0, y0;
long long dp1[][], dp2[][], c[][];
int move[] = {, -, , -}; void dp(long long dp[][], int start, int end, int x)
{
dp[][x] = ;
for (int i = ; i < k; i++)
{
for (int j = start; j <= end; j++)
if (dp[i][j])
{
for (int k = ; k < ; k++)
{
int ii = j + move[k];
if (ii >= start && ii <= end)
dp[i + ][ii] = (dp[i + ][ii] + dp[i][j]) % ;
}
}
}
}
void pl()
{
for (int i = ; i < ; i++)
c[i][] = ;
for (int i = ; i < ; i++)
for (int j = ; j <= i ; j++)
c[i][j] = (c[i - ][j - ] + c[i - ][j]) % ;
} int main()
{
int t;
int ans;
pl();
cin >> t;
for (int i = ; i <= t; i++)
{
cin >> n >> m >> k >> x0 >> y0; memset(dp1, , sizeof(dp1));
memset(dp2, , sizeof(dp2));
dp(dp1, , n, x0);
dp(dp2, , m, y0);
ans = ;
for (int j = ; j <= k; j++)
{
for (int ii = ; ii <= n; ii++)
dp1[j][] = (dp1[j][] + dp1[j][ii]) % ;
for (int ii = ; ii <= m; ii++)
dp2[j][] = (dp2[j][] + dp2[j][ii] ) % ;
}
for (int j = ; j <= k; j++)
ans = (ans + (((c[k][j] * dp1[j][]) % ) * dp2[k - j][]) % ) % ;
cout << "Case #" << i << ":" << endl << ans << endl;
}
return ;
}
2014年百度之星程序设计大赛 - 初赛(第二轮)Chess的更多相关文章
- 2014年百度之星程序设计大赛 - 初赛(第二轮)JZP Set
题目描述:一个{1, ..., n}的子集S被称为JZP集,当且仅当对于任意S中的两个数x,y,若(x+y)/2为整数,那么(x+y)/2也属于S.例如,n=3,S={1,3}不是JZP集,因为(1+ ...
- HDU 4834 JZP Set(数论+递推)(2014年百度之星程序设计大赛 - 初赛(第二轮))
Problem Description 一个{1, ..., n}的子集S被称为JZP集,当且仅当对于任意S中的两个数x,y,若(x+y)/2为整数,那么(x+y)/2也属于S.例如,n=3,S={1 ...
- HDU 4833 Best Financing(DP)(2014年百度之星程序设计大赛 - 初赛(第二轮))
Problem Description 小A想通过合理投资银行理财产品达到收益最大化.已知小A在未来一段时间中的收入情况,描述为两个长度为n的整数数组dates和earnings,表示在第dates[ ...
- HDU 4832 Chess(DP+组合数学)(2014年百度之星程序设计大赛 - 初赛(第二轮))
Problem Description 小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,“王”在棋盘上的走法遵循十字路 ...
- 2014年百度之星程序设计大赛 - 初赛(第一轮) hdu Grids (卡特兰数 大数除法取余 扩展gcd)
题目链接 分析:打表以后就能发现时卡特兰数, 但是有除法取余. f[i] = f[i-1]*(4*i - 2)/(i+1); 看了一下网上的题解,照着题解写了下面的代码,不过还是不明白,为什么用扩展g ...
- 2014年百度之星程序设计大赛 - 资格赛 第二题 Disk Schedule
双调欧几里得旅行商问题是一个经典动态规划问题.<算法导论(第二版)>思考题15-1和北京大学OJ2677都出现了这个题目. 旅行商问题描写叙述:平面上n个点,确定一条连接各点的最短闭合旅程 ...
- HDU6383 2018 “百度之星”程序设计大赛 - 初赛(B) 1004-p1m2 (二分)
原题地址 p1m2 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total ...
- HDU6380 2018 “百度之星”程序设计大赛 - 初赛(B) A-degree (无环图=树)
原题地址 degree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Tot ...
- HDU 6118 度度熊的交易计划 【最小费用最大流】 (2017"百度之星"程序设计大赛 - 初赛(B))
度度熊的交易计划 Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
随机推荐
- 在linux下Java的环境配置
最近开始学习Java语言. 对于我这种初学者来说,一开始,我想先体验,大致看了一下Java语言是什么,如何实现... 然并卵o_O,表示看得很迷糊.还是实践最重要,把环境配置好再开始深入学习. 1.首 ...
- DES算法
好久没写过博客啦,最近在gao搞Qt,做出漂亮的UI确实挺难的,做美工也不简单啊,好啦,言归正传,下面是实现DES的python源码,是借鉴了开源中国一个大师的源码写出来的,直接贴啦. 加密部分: # ...
- tabhost 下 setOnItemClickListener失效的问题
分析了一下代码,应该是tabhost 的ontabchangedListener接管了下面应该由setOnItemClickListener接管的部分,导致不能相应setOnItemClickList ...
- 在cmd命令行使用Maven Archetype插件 generate命令创建简单的java web项目
前提: 1.下载apache-maven:https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache ...
- 流行的JavaScript库 ——jQuery
1.为了简化 JavaScript 的开发, 一些 JavsScript 库诞生了. JavaScript 库封装了很多预定义的对象和实用函数.能帮助使用者建立有高难度交互的 Web2.0 特性的富客 ...
- VB.Net 2010中 ./和../的含义
文件路径 文件路径就是文件在电脑(服务器)中的位置,表示文件路径的方式有两种:相对路径和绝对路径. Windows由于使用 斜杆/ 作为DOS命令提示符的参数标志了,为了不混淆,所以采用 反斜杠\ 作 ...
- 浅谈Js原型的理解
一.js中的原型毫无疑问一个难点,学习如果不深入很容易就晕了! 在参考了多方面的资料后,发现解释都太过专业,对于很多还没有接触过面向对象 语言的小白来说,有理解不了里面的专有名词!如果你没 ...
- IOS_反射
// // PJReflect.m // 新浪微博 // // Created by pj on 14-8-8. // Copyright (c) 2014年 pj. All rights reser ...
- MVC学习二:基础语法
目录 一:重载方法的调用 二:数据的传递 三:生成控件 四:显示加载视图 五:强类型视图 六:@Response.Write() 和 @Html.Raw()区别 七:视图中字符串的输入 八:模板页 一 ...
- 剑指Offer面试题:20.栈的压入、弹出序列
一.题目:栈的压入.弹出序列 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1.2.3.4.5是某栈的压栈序列,序列4 ...