【ccf-201703-5】引水入城

试题编号: 201703-5
试题名称: 引水入城
时间限制: 2.0s
内存限制: 512.0MB
问题描述:
问题描述

  MF城建立在一片高原上。由于城市唯一的水源是位于河谷地带的湖中,人们在坡地上修筑了一片网格状的抽水水管,以将湖水抽入城市。如下图所示:
Paste_Image.png

  这片管网由 n 行 m 列节点(红色,图中 n = 5,m = 6),横向管道(紫色)和纵向管道(橙色)构成。
  行和列分别用 1 到 n 的整数和 1 到 m 的整数表示。第 1 行的任何一个节点均可以抽取湖水,湖水到达第 n 行的任何一个节点即算作引入了城市。
  除第一行和最后一行外,横向相邻或纵向相邻的两个节点之间一定有一段管道,每一段管道都有各自的最大的抽水速率,并需要根据情况选择抽水还是放水。对于纵向的管道(橙色),允许从上方向下方抽水或从下方向上方放水;如果从图中的上方向下方抽水,那么单位时间内能通过的水量不能超过管道的最大速率;如果从下方向上方放水,因为下方海拔较高,因此可以允许有任意大的水量。对于横向的管道(紫色),允许从左向右或从右向左抽水,不允许放水,两种情况下单位时间流过的水量都不能超过管道的最大速率。
  现在MF城市的水务负责人想知道,在已知每个管道单位时间容量的情况下,MF城每单位时间最多可以引入多少的湖水。

输入格式

  由于输入规模较大,我们采用伪随机生成的方式生成数据。
  每组数据仅一行包含 6 个非负整数 n, m, A, B, Q, X0。其中,n 和 m 如前文所述,表示管网的大小,保证 2 ≤ n, m ≤ 5000;保证 1 ≤ A, B, Q, X0 ≤ 109。
  A, B, Q, X0 是数据生成的参数,我们用如下的方式定义一个数列 { Xi }:
  Xi+1 = ( AXi + B) mod Q, (i ≥ 0)
  我们将数列的第 1 项到第 (n-1)m 项作为纵向管道的单位时间容量,其中 X(s-1)m+t 表示第 s 行第 t 列的节点到第 s+1 行第 t 列管道单位时间的容量;将数列的第 (n-1)m+1 项到第 (n-1)m+(n-2)(m-1) 项(即接下来的 (n-2)(m-1) 项)作为横向管道的单位时间容量,其中 X(n-1)m+(s-2)(m-1)+t 表示第 s 行第 t 列的节点到第 s 行第 t+1 列管道单位时间的容量。

输出格式

  输出一行一个整数,表示MF城每单位时间可以引入的水量。
  注意计算过程中有些参数可能超过32位整型表示的最大值,请注意使用64位整型存储相应数据。

样例输入

3 3 10 3 19 7

样例输出

38

样例说明

  使用参数得到数列 { Xi }={ 7, 16, 11, 18, 12, 9, 17, 2, 4, … },按照输入格式可以得到每个管道的最大抽水量如下图所示:
Paste_Image.png

  在标准答案中,单位时间可以引水 38 单位。所有纵向管道均向下抽水即可,不需要横向管道抽水,也不需要向上放水。

样例输入

2 5 595829232 749238243 603779819 532737791

样例输出

1029036148

样例输入

5 2 634932890 335818535 550589587 977780683

样例输出

192923706

样例输入

5 5 695192542 779962396 647834146 157661239

样例输出

1449991168

评测用例规模与约定

  共有10组评测数据,每组数据的参数规模如下所示:
Paste_Image.png
思路:

Paste_Image.png
代码:

import java.util.Scanner;

public class BringWaterintoCity {
    public static void main(String[] args) {
         Scanner sc = new Scanner(System.in);
            int n=sc.nextInt();
            int m=sc.nextInt();
            Long a =sc.nextLong();
            Long b=sc.nextLong();
            Long q=sc.nextLong();
            Long x0=sc.nextLong();
            int len=((n-1)*m+(n-2)*(m-1));
            Long[] xdatai=new Long[len];

            xdatai[0]=(a*x0+b)%q;

            for (int i = 1; i < len; i++) {
                xdatai[i]=(a*xdatai[i-1]+b)%q;   
            }

            int res=0;//结果

            //点
            Long[][] point=new Long[n-1][m];
            Long[][] out=new Long[n-1][m];//输出

            if(n==2) {
                for (int i = 0; i < m; i++) {
                    res += xdatai[i];
                }           
                System.out.println(res);
            }
            else
            {
                for (int i = 0; i < m; i++) {
                    point[0][i] = xdatai[i]; 
                }

                    for (int i = 1; i < n-1; i++) 
                        //初始化每列第1个                      
                        if(point[i-1][0] >= xdatai[i*m]){
                            point[i][0] = xdatai[i*m];
                            out[i][0] = point[i-1][0] - xdatai[i*m];
                            point[i-1][1] += Math.min(out[i][0], xdatai[(n-1)*m+i]);
                            //point[i-1][1] += out[i][0]< xdatai[(n-1)*m+i]?out[i][0]: xdatai[(n-1)*m+i];              
                        }
                        else{                           
                            point[i][0] = Math.min(point[i-1][0]+xdatai[(n-1)*m+(i-1)*(m-1)],xdatai[i*m]);
                            //point[i][0] = point[i-1][0] + xdatai[(n-1)*m+(i-1)*(m-1)]<xdatai[i*m]?point[i-1][0]+xdatai[(n-1)*m+(i-1)*(m-1)]:xdatai[i*m];                          
                            out[i][0] = point[i-1][0] - point[i][0];
                            point[i-1][1] += out[i][0];
                        }
                        for (int j = 1; j < m-1; j++) {
                            int bottom =i*m+j;
                            int right=(n-1)*m+(i-2)*(m-1)+j+1;
                            if(point[i-1][j] >= xdatai[bottom]) {
                                point[i][j] = xdatai[bottom];                          
                                out[i][j] = Math.min(point[i-1][j] - xdatai[bottom],xdatai[right]);
                                //out[i][j] =point[i-1][j] - xdatai[bottom] < xdatai[right]?point[i-1][j] - xdatai[bottom]:xdatai[right];
                                point[i-1][j+1] += out[i][j];
                            }
                            else
                            {       
                                //System.out.println((n-1)*m+i*m+j);
                                point[i][j] = Math.min(point[i-1][j]+xdatai[right],xdatai[bottom]);
                               // point[i][j] = point[i-1][j]+xdatai[right]<xdatai[bottom]?point[i-1][j]+xdatai[right]:xdatai[bottom];
                               out[i][j] = Math.min(point[i][j] - point[i-1][j],xdatai[right]);
                               // out[i][j] = point[i][j] - point[i-1][j] < xdatai[right]?point[i][j] - point[i-1][j]:xdatai[right];                          
                                point[i-1][j+1] -= out[i][j];
                            }
                        }           
                        point[i][m-1]=Math.min(point[i-1][m-1], xdatai[i*m+m-1]);
                       // point[i][m-1] = point[i-1][m-1] < xdatai[i*m+m-1]?point[i-1][m-1]: xdatai[i*m+m-1];
                    }

                    //输出
                    for (int i = 0; i < m; i++) {
                            res += point[n-2][i];
                    }
                    System.out.println(res);
            }                 
    }
}

结果:给出的几个测试用例都通过。但超时。后面再看看如何完善,希望大神来交流(~_~)
Paste_Image.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是第一段代码的解答: ccf201703-2是一个关于学生移位操作的问题。代码中使用了结构体来存储学生的编号和他在队伍中的位置,并通过重载运算符来对学生元素按照位置进行排序。首先,输入学生的数量n,并初始化一个vector来存储学生的信息。然后,根据学生的数量循环输入每个学生的编号和初始位置,并将其添加到vector中。接下来,输入移位操作的次数m,并循环输入每个移位操作的目标学生编号和移动的位置。根据目标学生编号,找到对应的学生在vector中的位置,并将其位置更新为目标位置。如果目标位置大于0,则将其前面的学生位置都减1;如果目标位置小于0,则将其后面的学生位置都加1。最后,对vector进行排序,并输出排序后的学生编号。 请注意,这段代码中使用了C++的一些语法和库函数,需要在编译时包含相关的头文件。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [CCF:201703-2 学生排队](https://blog.csdn.net/weixin_42729072/article/details/105435070)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [第十次ccf 学生排队](https://blog.csdn.net/xiaoli_nu/article/details/65468043)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [CCF-CSP 201703-2学生排队 一维数组满分题解](https://blog.csdn.net/m0_53641110/article/details/121446439)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值