「SFOI Round 1」Shade
题目背景
つづく日々の道の先を
塞ぐ影にアイデアを
雨の音で歌を歌おう
すべて越えて響け
つづく日々を奏でる人へ
すべて越えて届け
题目描述
小 F 很喜欢「アイデア」这首歌。
现在小 F 有一个 N × M N\times M N×M 格的方格纸,第 ( i , j ) (i,j) (i,j) 个格子上有 A i , j A_{i,j} Ai,j 层的「影子」。
小 F 想要把「影子」划破,他可以一次清除某一格上所有层的「影子」,但每清除一次就要消耗 1 1 1 点「妙意」,每清除 k k k 层「影子」可以恢复 1 1 1 点「妙意」,当小 F 没有「妙意」时,他就不能清除「影子」了。
小 F 现在有 t t t 点「妙意」,请你求出他最多可以清除多少层「影子」。
输入格式
输入共 N + 1 N+1 N+1 行。
第 1 1 1 行 4 4 4 个整数,分别表示方格纸的长度 N N N、宽度 M M M 以及恢复「妙意」所需清除「影子」的层量 k k k 和小 F 初始时拥有「妙意」的点数 t t t。
第 2 2 2 至 N + 1 N+1 N+1 行,每行 M M M 个整数,分别表示该格子上的「影子」的层数 A i , j A_{i,j} Ai,j。
输出格式
输出共 1 1 1 行 1 1 1 个整数,表示可以清除「影子」层数的最大值。
样例 #1
样例输入 #1
3 3 5 1
1 2 3
4 5 6
7 8 9
样例输出 #1
45
提示
【样例 1 解释】
初始时共 1 1 1 点「妙意」。
操作 | 剩余「妙意」点数 | 清除「影子」层数 | 共计清除「影子」层数 |
---|---|---|---|
清除 ( 3 , 3 ) (3,3) (3,3) | 0 0 0 | 9 9 9 | 9 9 9 |
恢复「妙意」 | 1 1 1 | 4 4 4 | 9 9 9 |
清除 ( 3 , 2 ) (3,2) (3,2) | 0 0 0 | 12 12 12 | 17 17 17 |
恢复「妙意」 | 2 2 2 | 2 2 2 | 17 17 17 |
清除 ( 3 , 1 ) (3,1) (3,1) | 1 1 1 | 9 9 9 | 24 24 24 |
恢复「妙意」 | 2 2 2 | 4 4 4 | 24 24 24 |
清除 ( 2 , 3 ) (2,3) (2,3) | 1 1 1 | 10 10 10 | 30 30 30 |
恢复「妙意」 | 3 3 3 | 0 0 0 | 30 30 30 |
清除 ( 2 , 2 ) (2,2) (2,2) | 2 2 2 | 5 5 5 | 35 35 35 |
恢复「妙意」 | 3 3 3 | 0 0 0 | 35 35 35 |
清除 ( 2 , 1 ) (2,1) (2,1) | 2 2 2 | 4 4 4 | 39 39 39 |
清除 ( 1 , 3 ) (1,3) (1,3) | 1 1 1 | 7 7 7 | 42 42 42 |
恢复「妙意」 | 2 2 2 | 2 2 2 | 42 42 42 |
清除 ( 1 , 2 ) (1,2) (1,2) | 1 1 1 | 4 4 4 | 44 44 44 |
清除 ( 1 , 1 ) (1,1) (1,1) | 0 0 0 | 5 5 5 | 45 45 45 |
恢复「妙意」 | 1 1 1 | 0 0 0 | 45 45 45 |
以上剩余「妙意」点数、清除「影子」层数和共计清除「影子」层数均指操作后。
综上,可以清除方格纸上所有的「影子」,故为 45 45 45。
【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ N , M , t ≤ 1 0 6 1\le N,M,t\le10^6 1≤N,M,t≤106, 1 ≤ k ≤ 1 0 18 1\le k\le10^{18} 1≤k≤1018, 1 ≤ A i , j ≤ 1 0 9 1\le A_{i,j}\le10^9 1≤Ai,j≤109 且 1 ≤ N × M ≤ 1 0 6 1\le N\times M\le10^6 1≤N×M≤106。
Point \text{Point} Point | N , M ≤ N,M\le N,M≤ | Note \text{Note} Note |
---|---|---|
1 1 1 | 10 10 10 | Yes \text{Yes} Yes |
2 2 2 | 10 10 10 | No \text{No} No |
3 3 3 | 200 200 200 | Yes \text{Yes} Yes |
4 4 4 | 200 200 200 | No \text{No} No |
5 5 5 | 1 0 3 10^3 103 | Yes \text{Yes} Yes |
6 6 6 | 1 0 3 10^3 103 | No \text{No} No |
7 ∼ 8 7\sim8 7∼8 | 1 0 6 10^6 106 | Yes \text{Yes} Yes |
9 ∼ 10 9\sim10 9∼10 | 1 0 6 10^6 106 | No \text{No} No |
Note \text{Note} Note:保证 k = 1 0 18 \bf k=10^{18} k=1018。
设计思路
这道题就是典型的模拟+贪心题,只是题目有点长,按照题目的要求来,细节,因为k会爆int,因此要开long long
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N = 1e6+10;
#define int long long
vector<int>p;
int n,m,k,t;
signed main(){
cin>>n>>m>>k>>t;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int x;
cin>>x;
p.push_back(x);
}
}
sort(p.begin(),p.end(),greater<int>());//直接贪心
int m=p.size();
int res=0;
int t1=0,t2=0,t3=0,t4=0;
for(int i=0;i<m;i++){
if(t>=0){
t--;
if(t<0)break;
res+=p[i];
t4=p[i]+t2;
t1=t4/k*k;//总的消费成体力的量
}
t2=t4-t1;//剩下的
if(t1>=k){
t3=t4/k;//总的能恢复的体力值
t+=t3;
}
}
cout<<res;
return 0;
}