方块游戏—题解

1590 - 方块游戏

Time Limit: 1s Memory Limit: 128MB

Submissions: 33 Solved: 13

DescriptionBG和ZZ一起玩一个游戏,游戏规则如下:

游戏开始时画在一张纸上,纸上画有n*m个方块组成的格子,BG和ZZ轮流玩这个游戏,BG先开始。每一轮玩家都会在上一次的方框内框出一个小方框作为下一轮的方框,这个小方框的边和原先的方框的边不能够有交集。

这个游戏没有赢家,BG和ZZ只是不断的缩小方框,直到游戏进行k轮。现求游戏有多少种方法。(即游戏从初始状态到进行k轮后的任意状态的路径数目)。Input输入包括多组数据,每组数据为一行,每行有3个整数n,m,k(其中1?≤?n,?m,?k?≤?1000)。Output每组数据输出一行,每行为一个整数ans,表示游戏的方法数量,由于数量可能很大,请输出答案对1000000007求余的结果。

Sample Input3 3 1

4 4 1

6 7 2

Sample Output1

9

75

方法一:(模拟)

import java.util.Scanner;

public class Asist
{
	/**
	 *   (1)
	 *    dp1[i][j] 代表  (i+2) * (j+2)个方块组成的格子进行 1 轮的总方法数 !(数学归纳法获知的!——可以打印出来看看)
	 *
	 *   (2)
	 *    关于这个式子:sum=sum+test(k-1, i-2, j-2)*(n-i+1)*(m-j+1);
	 *      a) test(k, i, j) 求的是  i * j 个方块组成的格子进行k轮的总可行数! (废话了!)
	 *
	 *      b) 至于这个式子的来历,我举个实际例子吧,(一般我的解题思路都是先举出一个实际例子、然后对其他情况加以证明而完成的、)
	 *
	 *    1. 对于给定的n, m, k, 必须满足  n >= 2k+1 && m >= 2k+1才可有可行方案,否则输出 0;  (很容易证明, 也是关键点!)
	 *
	 *    例子:
	 *         n  m  k
	 *         7  8  3
	 *     说明:  每进行一轮时, 此时方框的最外层是不可取的, 也就是说,实际最大可取方框为 (n-2) *  (m-2)
	 *
	 *    第一轮, 应至少取出   x * y 个方框,(其中 n >= x >= 2*k - 1 && m >= y >= 2*k - 1  ),此时 n = 5, m = 6, k = 3,
	 *           这样做方面配合我的 dp1[][]数组,才这样的。
	 *         这一轮的可行取法有:
	 *                           i,j
	 *                       1.  5,5      这种取法的方式有 2 次       ——
	 *                                                        次数  = (n-i+1) * (m-j+1) (很容易证明)
	 *                       2.  5,6      这种取法的方式有 1次       ——
	 *
	 *    第二轮, 根据前一轮的答案,同理的做法。 第一轮中有两种符合的情况:
	 *      1.   n  m  k
	 *           5  5  2
	 *        完成一轮操作, 应至少取出   x * y 个方框,(其中 n >= x >= 2*k - 1 && m >= y >= 2*k - 1  ),此时 n = 3, m = 3, k = 2,
	 *      这种情况,这一轮的取法有:
	 *                      i, j
	 *                   1. 3, 3  这种取法的方式有1次
	 *      2.  n  m  k
	 *          5  6  2
	 *        完成一轮操作, 应至少取出   x * y 个方框,(其中 n >= x >= 2*k - 1 && m >= y >= 2*k - 1  ),此时 n = 3, m = 4, k = 2,
	 *      这种情况,这一轮的取法有:
	 *                      i, j
	 *                   1. 3, 3  这种取法的方式有2次
	 *                   2. 3, 4 这种取法的方式有1次
	 *     第三轮,根据前一轮的答案,同理
	 *      1.  n  m  k
	 *          3  3  1
	 *         当 k = 1时,就好说了, 因为我的dp1[] 就是解决 k=1的。  此时n = 1, m = 1, k = 1,
	 *         结果是: dp[1][1] * 1(第三轮1次) * 1(第二轮1次) * 2(第一轮2次) = 2
	 *      2.  n  m  k
	 *          3  3  1
	 *         结果是: dp[1][1] * 1(第三轮1次) * 2(第二轮2次) * 1(第一轮1次) = 2
	 *      3.  n  m  k
	 *          3  4  1
	 *         结果是: dp[1][2] * 1 * 1 * 1 = 3;
	 *
	 *       综上所述:   sum = 2 + 2 + 3 = 7;
	 */
	public static final int MOD = 1000000007;
	public static int dp1[][];                            // 记录一个初始状态
	public static long dp2[][] = new long[1000][1000];    // 记忆化搜索
	public static void main(String[] args)
 	{
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = sc.nextInt();

		// 初始化 dp1 数组
		 dp1 = new int[1000][1000];
		for (int i = 1; i < 1000 ; i++)
		{
		    dp1[1][i] = i * (i+1) / 2;
		    dp1[i][1] = dp1[1][i];
		}
		for (int i = 2; i < 1000; i++)
		{
			for (int j = 2; j < 1000; j++)
			{
			   dp1[i][j] = dp1[i][1] * dp1[1][j];
			}
		}

	   //模拟游戏
	    System.out.println(test(k, n-2, m-2));
 	}

	private static long test(int k, int n, int m)
	{
		if (k == 1)
		{
			return dp1[n][m];
		}
		if (dp2[n][m]!=0) return dp2[n][m];

		long sum = 0;
		int temp = 2*k-1;

		for (int i = temp; i <= n; i++)
		{
			for (int j = temp; j <= m; j++)
			{
				sum = (sum + (test(k-1, i-2, j-2)%MOD * (n-i+1)%MOD * (m-j+1)%MOD) % MOD)%MOD;
			}
		}

		dp2[n][m] = sum;   // 记忆
		return sum;
	}
}

方法二:(组合数学问题) 上代码

import java.util.Scanner;

public class Main
{
	public static final int MOD = 1000000007;
	public static void main(String[] args)
 	{
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = sc.nextInt();

		System.out.println(test(2*k,n-1)*test(2*k,m-1)%MOD);
 	}

	private static long test(int n, int m)
	{
         if (n > (m / 2)) n = m-n;

         long sum = 1;
         for (int i = 0; i < n; i++) sum = (sum * (m-i)) % MOD;
         long sun = 1;
         for (int i = 2; i <= n; i++) sun = (sun * i) % MOD;

         return sum / sun;
	}
}

时间: 2024-12-17 03:51:58

方块游戏—题解的相关文章

hust 1590 - 方块游戏 数学

1590 - 方块游戏 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/problem/show/1590 Description BG和ZZ一起玩一个游戏,游戏规则如下:        游戏开始时画在一张纸上,纸上画有n*m个方块组成的格子,BG和ZZ轮流玩这个游戏,BG先开始.每一轮玩家都会在上一次的方框内框出一个小方框作为下一轮的方框,这个小方框的边和原先的方框的边不能够有交集.        这个游

codevs 1512 转向游戏 题解

Codevs 1512转向游戏 题解 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 白银 Silver 题解 题目描述 Description 小明自认为方向感很好,请小红来测试.小红先让小明面对北方立正站好,然后发出"向左转""向右转"或"向后转"的命令.每个命令执行后,小明都正确地说出了他面对的方向.小红的命令共N个(1≤n≤10000),请你统计小明说[南]的次数. 命令是以数字方式表达: 0---向左转 1---向右转 2

bzoj 1874 取石子游戏 题解 &amp; SG函数初探

[原题] 1874: [BeiJing2009 WinterCamp]取石子游戏 Time Limit: 5 Sec  Memory Limit: 162 MB Submit: 334  Solved: 122 [Submit][Status] Description 小H和小Z正在玩一个取石子游戏. 取石子游戏的规则是这样的,每个人每次可以从一堆石子中取出若干个石子,每次取石子的个数有限制,谁不能取石子时就会输掉游戏. 小H先进行操作,他想问你他是否有必胜策略,如果有,第一步如何取石子. In

Js练手---打方块游戏

javascript练手---打方块游戏

第八讲:HTML5中canvas实现小球击打小方块游戏

源代码:http://download.csdn.net/detail/liumingm900913/7469969 游戏开发流程: 1.创建画布: 将画布放在div标签里面,这样可以控制画布居中的位置,在对div标签加上一些样式,利于观看 <div id="main"> <!--将画布嵌在div块里面,使其可以居中--> <canvas id="liuming_canvas" width="300px" heigh

luogu P5092 [USACO2004OPEN]Cube Stacking 方块游戏

题目描述 约翰和贝茜在玩一个方块游戏.编号为 1…n 1\ldots n 1…n 的 n n n ( 1≤n≤30000 1 \leq n \leq 30000 1≤n≤30000 )个方块正放在地上,每个构成一个立方柱. 游戏开始后,约翰会给贝茜发出 P P P ( 1≤P≤100000 1 \leq P \leq 100000 1≤P≤100000 )个指令.指令有两种: 移动(M):将包含X的立方柱移动到包含Y的立方柱上. 统计(C):统计含X的立方柱中,在X下方的方块数目. 写个程序帮贝

阿狸和桃子的游戏题解

阿狸和桃子的游戏题解 每一道代码简单的黑题都有着诡异的思想,真不知道出题者怎么想的. 而这道题的重点在于把边权转换为点权, 此题的方式是将边权w平均分给被连接的两点u和v. 若u和v都被一人选择,则他的分数较不加边权前多了w/2+w/2=w, 若被不同的人选择,分数差多了(ans1+w/2)-(ans2-w/2)=ans1-ans2 并不会对答案有什么影响. 所以,最优策略? 肯定选择点权最大的了. 排序后依次选择即可. #include<bits/stdc++.h> using namesp

html5消除方块游戏总结-对象

在短短2周内,做了2个项目,虽然时间很紧凑,很累,但我觉得这很充实,在每次的实战项目演练过程中都能发现许多平常不遇到的问题,也只有实际操作项目,才能让我所学知识活学活用,并且能够更快的适应实际工作中的项目. 这周做的是一个小游戏,一个小人物根据相同的颜色来消除方块的项目,虽然做游戏的时间很短暂,但我觉得我收获颇丰,不断的学习,让我觉得更踏实,虽然累,我也觉得很值得,这次项目主要让我们理解和使用面向对象编程这个概念. 对象是一个抽象的概念,是一种面对人的思维方式,人有特征,就如对象里的属性,而人有

洛谷 P1005 矩阵取数游戏 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=1005 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2.每次取走的各个元素只能是该元素所在行的行首或行尾: 3.每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分 = 被取走的元