题目链接
普及题:
http://acm.zzuli.edu.cn/problem.php?id=1210
提高题:
http://acm.zzuli.edu.cn/problem.php?id=1394
普及题
当东东每天时间重合的时候就不能够陪多个女朋友,所以找到重合的人数最多的时间段,就是东东需要的最少天数。
这种时间段问题都可以用差分和前缀和,优化一下时间复杂度。
#include<bits/stdc++.h>
using namespace std;
int arr[30];
int main(){
int t, n, l, r;
cin >> t;
while(t--){
memset(arr, 0, sizeof(arr));
cin >> n;
for(int i = 0; i < n; i++){
cin >> l >> r;
arr[l]++;
arr[r+1]--;
}
int ans = 0, num = 0;
for(int i = 1; i <= 24; i++){
num += arr[i];
ans = max(ans, num);
}
cout << ans << endl;
}
}
提高题
按照题目意思,只能从编号小的城市走到编号大的城市。
一种方法是用深搜,遍历所有能走的方式,比较所需的最短距离。不过直接用深搜会超时。所以需要剪一下枝:当前所需的距离大于已知的最小距离时,就不需要继续下去了,因为一定不是最小的距离。
#include<bits/stdc++.h>
using namespace std;
int arr[105][105], ans = 1e9;
//begin:当前所处的城市编号, n:总数目, v:当前已经经过的距离
void dfs(int begin, int n, int v){
if(v > ans) return;
if(begin == n){
ans = min(ans, v);
return;
}
for(int i = begin+1; i <= n; i++){
if(arr[begin][i]){
dfs(i, n, v+arr[begin][i]);
}
}
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int t, n;
cin >> t;
while(t--){
cin >> n; ans = 1e9;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
cin >> arr[i][j];
}
}
dfs(1, n, 0);
cout << ans << endl;
}
}
还有一种方法是用动态规划思想。每次只能由编号小的城市走到编号大的城市,所以按编号从小到大,寻找Lh到每一个城市的最短距离,到第i城的最短距离,一定是i前面城市的最短距离再加上前面城市到i城的距离中的某一个。
最后输出到城市n的最短距离即可。
#include<bits/stdc++.h>
using namespace std;
int arr[105][105];
int dp[105]; // dp[i]: 从城市1到城市i的最短距离。
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int t, n;
cin >> t;
while(t--){
memset(dp, 127, sizeof(dp));
cin >> n;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
cin >> arr[i][j];
}
}
dp[1] = 0;
for(int i = 2; i <= n; i++){
for(int j = 1; j < i; j++){
if(arr[i-j][i])
dp[i] = min(dp[i], dp[i-j] + arr[i-j][i]);
}
}
cout << dp[n] << endl;
}
}