题目链接
普及题:
http://acm.zzuli.edu.cn/problem.php?id=2531
提高题:
http://acm.zzuli.edu.cn/problem.php?id=2532
普及题
2531: 土豪婷婷请吃饭
思路: 用数组的下标作为时间段,把每次输入的进场时间与出场时间中间的时间段都加一,输入完后统计这个数组上的最大数,就是同时在场人数最多的时候。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n, arr[505];
while(cin >> n){
memset(arr, 0, sizeof(arr));
int ans = 0, l, r;
for(int i = 0; i < n; i++){
cin >> l >> r;
for(int j = l; j <= r; j++){
arr[j]++;
}
}
for(int i = 0; i < 505; i++){
ans = max(ans , arr[i]);
}
cout << ans << endl;
}
}
事实上当数据很大时这种方法很容易超时(这题数据小,不会超时)。
比如这题https://ac.nowcoder.com/acm/problem/209813
如果直接暴力的话就会超时。这时就需要用到一个小技巧:前缀和与差分。
一维的前缀和就是数组前n项的和,差分是用来维护这个数组的方式。合理利用这种方式可以有效的节省时间。
这个博客讲的比较详细点击跳转
本题用前缀和差分实现的代码如下
#include<bits/stdc++.h>
using namespace std;
int arr[505];
int main(){
int n, l, r;
while( ~scanf("%d",&n) ){
int ans = 0, num = 0;;
memset(arr, 0, sizeof(arr));
for(int i = 0; i < n; i++){
scanf("%d %d",&l,&r);
arr[l]++; arr[r+1]--;
}
for(int i = 0; i < 502; i++){
num += arr[i];
ans = max(ans, num);
}
printf("%d\n", ans);
}
}
提高题
2532: 婷婷是土豪
我的思路是用递归,枚举出每一次的情况。如果符合条件就继续递归下去,直到借钱与还钱的人数都为0时。具体见代码
#include<bits/stdc++.h>
using namespace std;
int ans = 0;
// m:剩余还钱人数 n:剩余借钱人数 v:本金
void dfs(int m, int n, int v){
if(m == 0 && n == 0) //借钱与还钱人数都为0时,则是一种方案
ans++;
if(m > 0) //如果还钱人数>0
dfs(m-1, n, v+1);
if(n > 0 && v > 0) // 借钱人数>0时并且本金>0时。有人借钱时 本金一定要大于0
dfs(m, n-1, v-1);
}
int main(){
int m, n;
while(cin >> m >> n){
ans = 0;
dfs(m, n, 0);
cout << ans << endl;
}
}