51nod-1293 球与切换器

题目来源:  Codility
基准时间限制:1 秒 空间限制:131072 KB 分值: 80  难度:5级算法题
 收藏
 关注
有N行M列的正方形盒子。每个盒子有三种状态0, -1, +1。球从盒子上边或左边进入盒子,从下边或右边离开盒子。规则:
如果盒子的模式是-1,则进入它的球从下面出去。(方向变为向下)
如果盒子的模式是+1,则进入它的球从右面出去。 (反向变为向右)
如果盒子的模式是0, 则进入它的球方向不变。从上面进入的,从下面出去,从左面进入的,从右面出去。


球离开一个盒子,这个盒子的模式切换为相反数。已知,每个盒子的状态,扔k个球,它们都从左上角那个盒子的上面进入(方向向下),问最终有几个球从右下角的盒子的下边出去。
(可以理解维球一个一个放,等待的时间足够长,不会有两个球同时进入一个盒子的情形)本题由Javaman翻译。
Input
第1行:包括3个数M, N, K中间用空格分隔,M,N 为盒子的宽度和高度,K为球的数量(1 <= M, N <= 1000, 1 <= K <= 10^18)。
第2 - N + 1行:每行M个数(-1, 0 或 1),表示对应的模式。
Output
输出1个数,对应最终有有多少个球从右下角的盒子的下边出去。
Input示例
3 2 4
-1 0 -1
1 0 0
Output示例
1

题解:设dp[0][i][j]为从i行j列向下出去球的数量,dp[1][i][j]为i行j列向右出去球的数量。则能到达i行j列只能从i行j - 1列向右,i - 1行j列向下。如果i行j列为0,则进来方向和出去方向相同。如果是1,则进来的求先向右,后向下。。很明显发现奇数情况向右比向下多1,偶数相同。如果是-1,跟1时同样讨论即可。

感觉是水题啊,我居然都做出来了。这是假的五级算法题吧!

AC代码

#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cmath>
typedef unsigned long long ll;

using namespace std;

const ll maxn = 1e3 + 10;
ll dp[2][maxn][maxn], a[maxn][maxn];

int main(){
	ll n, m, k;
	scanf("%llu %llu %llu", &m, &n, &k);
	for(ll i = 1; i <= n; i++)
		for(ll j = 1; j <= m; j++)	
			scanf("%llu", &a[i][j]);
	dp[0][0][1] = k;
	for(ll i = 1; i <= n; i++){
		for(ll j = 1; j <= m; j++){
			if(a[i][j] == 0){
				dp[0][i][j] = dp[0][i - 1][j];
				dp[1][i][j] = dp[1][i][j - 1];
			}
			else if(a[i][j] == -1){
				ll tmp = dp[0][i - 1][j] + dp[1][i][j - 1];
				dp[1][i][j] = tmp / 2;
				dp[0][i][j] = tmp - dp[1][i][j];
			}
			else{
				ll tmp = dp[0][i - 1][j] + dp[1][i][j - 1];
				dp[0][i][j] = tmp / 2;
				dp[1][i][j] = tmp - dp[0][i][j];
			}
		}
	}
	printf("%llu\n", dp[0][n][m]);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/qq_37064135/article/details/80454522
今日推荐