zoukankan      html  css  js  c++  java
  • 51Nod 1293 球与切换器 DP分类

    基准时间限制:1 秒 空间限制:131072 KB
     
    有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
    可以整体考虑,因为落下一个,就会改变当前的值为相反数,所以一方为n+1/2,一方为n/2
    类似考虑,当为+1时,优先考虑对下个右方格子的影响,-1时优先考虑下个左方格子的影响,为0时直接加和
    代码:
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int dir;
     4 long long dp[1002][1001][2];
     5 long long read(){
     6     long long res = 0;
     7     int flag = 0;
     8     char ch;
     9     if ((ch = getchar()) == '-'){
    10         flag = 1;
    11     }
    12     else if(ch >= '0' && ch <= '9'){
    13         res = ch - '0';
    14     }
    15     while ((ch = getchar()) >= '0' && ch <= '9'){
    16         res = res * 10 + (ch - '0');
    17     }
    18     return flag ? -res : res;
    19 }
    20 int main() {
    21     int n,m;
    22     long long k;
    23     m=read();n=read();k=read();
    24     //用0来表示-1朝下,1来表示+1朝右
    25     //刚开初始放下为朝下,全部球落入dp[1][1][0],dp[1][1][1]=0;
    26     dp[1][1][0]=k;
    27     for(int i=1;i<=n;++i) {
    28         for(int j=1;j<=m;++j) {
    29             //不同再开数组保存方向,因为一行一行处理没有后效性
    30             dir=read();
    31             long long sum=dp[i][j][0]+dp[i][j][1];//当前关口的总数
    32             if(dir==0) {
    33                 dp[i][j+1][1]+=dp[i][j][1];//朝右j+1
    34                 dp[i+1][j][0]+=dp[i][j][0];//朝下i+1
    35             } else if(dir==-1) {
    36                 dp[i+1][j][0]+=(sum+1)>>1;//先计算朝下的,i+1,状态0
    37                 dp[i][j+1][1]+=sum>>1;//剩余的朝右j+1,状态1
    38             } else if(dir==1) {
    39                 dp[i][j+1][1]+=(sum+1)>>1;//先计算朝右的,j+1,状态1
    40                 dp[i+1][j][0]+=sum>>1;//剩余的朝右i+1,状态0
    41             }
    42         }
    43     }
    44     printf("%lld
    ",dp[n+1][m][0]);//由dp[n][m][0]->dp[n+1][m][0]
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    这几个C++的坑,一旦踩中了,加班是肯定避免不了了!
    2020年11月编程语言排行榜:Java再掉一位排名,真的要跌落神坛了吗?
    自学编程的朋友想要了解怎么快速入门,我想给你这5个建议!
    来看看这些获奖的C语言程序!一个比一个秀,这就是强者的世界吗!
    【每天学点新知识】Linux操作系统下C语言多线程同步使用指南!
    听说IT行业只有高智商的人才能进得去,而且以男性居多,还必须专业对口?
    假如C++是一只箭,你会用它来射哪只雕?
    程序员常见的口头禅,最后一个笑掉大牙,网友:真实的一批!
    Python基础语法
    Python—“helloworld”
  • 原文地址:https://www.cnblogs.com/lemonbiscuit/p/7775953.html
Copyright © 2011-2022 走看看