51Nod-球与切换器-1293

本文介绍了关于球与切换器的编程题目,讨论了如何处理球在不同模式盒子中的运动,以及如何通过三维数组解决超时问题。给出了解题思路和代码实现,最终输出从右下角盒子下边离开的球数。
李陶冶  (命题人)
基准时间限制:1 秒 空间限制:131072 KB 分值: 80
有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
解题思路:这道题我刚开始想的思路是用搜索做,后来考虑到k太大,非常容易超时,借鉴了大神的想法,用三维数组来做的。res[i][j][0]表示从此位置要向下的球数,res[i][j][1]表示从此位置要向右的球数。
解题代码:
#include<iostream>
#include<stdio.h>
using namespace std;
const int MAXN=1005;
int ch[MAXN][MAXN];
long long res[MAXN][MAXN][2],K;
int read()
{
    char c;int s=0,t=1;
    while(!isdigit(c=getchar()))if(c=='-')t=-1;
    do{s=s*10+c-'0';}while(isdigit(c=getchar()));
    return s*t;
}
int main()
{
    int N,M;
    scanf("%d%d%lld",&M,&N,&K);
    long long tmp;
    for(int i=1;i<=N;i++)
        for(int j=1;j<=M;j++)
        ch[i][j]=read();
    res[0][1][0]=K;
    for(int i=1;i<=N;i++)
        for(int j=1;j<=M;j++)
    {
        long long tmp=res[i-1][j][0]+res[i][j-1][1];
        if(ch[i][j]==-1)
        {
            res[i][j][0]=(tmp+1)/2;//由于每个球走后此处只会变成相反数,所以需要除以2,同下
            res[i][j][1]=tmp-(tmp+1)/2;
        }
        if(ch[i][j]==1)
        {
            res[i][j][1]=(tmp+1)/2;
            res[i][j][0]=tmp-(tmp+1)/2;
        }
        if(ch[i][j]==0)
        {
            res[i][j][0]=res[i-1][j][0];
            res[i][j][1]=res[i][j-1][1];
        }
    }
    printf("%lld\n",res[N][M][0]);
    return 0;
}


### 关于51Nod平台上编号为1020的问题详情解答 #### 问题描述 在51Nod平台上的第1020号问题是关于计算两个大整数相加的结果[^1]。给定两个正整数A和B,长度不超过10^6位,要求编写程序来求解这两个数的和。 #### 输入格式说明 输入数据由多组测试案例组成;每组测试案例占两行,分别表示要相加的大整数A和B。对于每一组测试案例,应当单独输出一行结果,即A+B的值。 #### 解决方案概述 解决此问题的关键在于处理超大数据类型的运算,在大多数编程语言中内置的数据类型无法直接支持如此大规模数值的操作。因此,可以采用字符串的方式来存储这些大整数,并实现逐位相加逻辑,同时考虑进位情况。 下面是一个Python版本的具体实现方法: ```python def add_large_numbers(a: str, b: str) -> str: # Reverse strings to make addition easier from least significant digit a = a[::-1] b = b[::-1] carry = 0 result = [] max_length = max(len(a), len(b)) for i in range(max_length): digit_a = int(a[i]) if i < len(a) else 0 digit_b = int(b[i]) if i < len(b) else 0 total = digit_a + digit_b + carry carry = total // 10 current_digit = total % 10 result.append(str(current_digit)) if carry != 0: result.append(str(carry)) return ''.join(reversed(result)) if __name__ == "__main__": while True: try: num1 = input().strip() num2 = input().strip() print(add_large_numbers(num1, num2)) except EOFError: break ``` 该代码片段定义了一个函数`add_large_numbers`用于接收两个作为参数传入的大整数(形式上为字符串),并返回它们之和同样作为一个字符串。通过反转输入字符串使得最低有效位位于索引位置0处从而简化了按位累加的过程。最后再将得到的结果列表反向拼接成最终答案输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值