题目描述
给定一个媒体包序列号列表,计算发送该媒体包的最少发送源个数。每个发送源发送的媒体包序列号不会重复,且每次加1(不考虑回绕问题,65535是发送源发送的最后一个媒体包序列号)。如果收到的媒体包序列号不满足该规则,则这些媒体包必然来自多个发送源。
输入描述
第一行:seqs
列表长度 ( n )。
第二行:seqs
列表元素,元素之间通过空格隔开。
输出描述
输出最少媒体包发送源个数。
用例输入
输入:
11
1 2 3 4 5 6 7 8 9 10 10
输出:
2
说明:
媒体包发送源 1:1 2 3 4 5 6 7 8 9 10
媒体包发送源 2:10
媒体发送源个数为 2,因此输出 2。
解题思路
问题分析
- 序列号规则:每个发送源发送的媒体包序列号是连续的,且不会重复。
- 目标:计算最少的发送源个数。
- 关键点:如果某个序列号 ( num ) 的前一个序列号 ( num - 1 ) 存在,则它们可以属于同一个发送源;否则,它们属于不同的发送源。
算法设计
-
使用动态规划数组:
- 创建一个大小为 65536 的数组
dp
,用于记录以当前值为结束点的连接数量。 - 初始化所有值为 0。
- 创建一个大小为 65536 的数组
-
遍历输入序列号:
- 对于每个序列号 ( num ):
- 如果 ( num - 1 ) 存在(即
dp[num - 1] > 0
),则将 ( num - 1 ) 的计数减 1,表示num可以被连接到num - 1。 - 同时,将 ( num ) 的计数加 1,表示当前序列号是一个新的结束点。
- 如果 ( num - 1 ) 存在(即
- 对于每个序列号 ( num ):
-
计算结果:
- 遍历
dp
数组,统计所有非零值的个数,即为最少发送源个数。
- 遍历
代码
cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, num;
cin >> n; // 输入序列号列表长度
vector<int> dp(65536, 0); // 动态规划数组
for (int i = 0; i < n; i++) {
cin >> num; // 输入序列号
if (num > 0 && dp[num - 1] > 0) {
// 如果前一个序列号存在,则它们可以连接
dp[num - 1]--;
}
dp[num]++; // 当前序列号计数加1
}
int res = 0;
for (int i = 0; i < 65536; i++) {
res += dp[i]; // 统计所有非零值的个数
}
cout << res << endl; // 输出结果
return 0;
}