dp|中位数贪心+裴蜀定理
lc467
中位数贪心
class Solution {
public:
int minMoves2(vector<int>& nums) {
int m = nums.size() / 2;
ranges::nth_element(nums, nums.begin() + m);
int median = nums[m];
int ans = 0;
for (int x : nums) {
ans += abs(x - median);
}
return ans;
}
};
lc2607
每组对应位置中位数贪心
for (int j = i; j < n; j += g)
group.push_back(arr[j]);
sort(group.begin(), group.end());
int mid = group[group.size() / 2];
裴蜀定理(gcd(n, k) 是循环节的大小,进行分组处理)(飞鼠定理bush
两个整数的最大公约数,等于这两个数通过整数倍加减能得到的最小正整数(且仅当它们的线性组合能凑出1时互质)
对于整数 a、b,存在整数 x、y 使得 ax + by = d 的充要条件是 gcd(a,b) | d(gcd 是最大公约数,“|”表示整除)
typedef long long ll;
class Solution {
public:
long long makeSubKSumEqual(vector<int>& arr, int k)
{
int n = arr.size();
ll ret = 0;
int g = gcd(n, k);
for (int i = 0; i < g; ++i) {
vector<int> group;
for (int j = i; j < n; j += g)
group.push_back(arr[j]);
sort(group.begin(), group.end());
int mid = group[group.size() / 2];
for (int num : group) {
ret += abs(num - mid);
}
}
return ret;
}
};
错误思路
class Solution {
typedef long long ll;
public:
long long makeSubKSumEqual(vector<int>& arr, int k)
{
int n=arr.size();
ll ret=0;
vector<ll> presum(2*n+1,0);
for(int i=1;i<2*n;i++)
{
presum[i]=presum[i-1]+arr[(i-1)%n];
}
ll prediff=presum[k]-presum[0];
for(int i=k+1;i<2*n;i++)
{
ll diff=presum[i]-presum[i-k];
ret+=abs(diff-prediff);
prediff=diff;
}
return ret/2;
}
};
lc3332
1. 定义状态
dp[i][j] :第 i 天处于城市 j 时能获得的最大点数。
2. 初始化状态
第 0 天(还没开始旅游),不管在哪个城市,点数都是 0 ,即 f[0][j] = 0 (所有 j )
3. 方程
- 停留情况:第 i 天留在城市 j ,则点数由“第 i-1 天在 j 的点数 + 当天停留得分”转移而来,即 f[i][j] = f[i-1][j] + stayScore[i-1][j] 。
- 移动情况:第 i 天从城市 jj 移动到 j ( jj≠j ),则点数由“第 i-1 天在 jj 的点数 + 移动得分”转移而来,即 f[i][j] = max(f[i][j], f[i-1][jj] + travelScore[jj][j]) 。
4. 遍历计算所有状态
从第 1 天到第 K 天,逐个城市计算 dp[i][j] 的值。
5. 求解最终结果
遍历第 K 天所有城市的最大点数,取最大值即为答案。
class Solution {
public:
int maxScore(int n, int K, vector<vector<int>>& stayScore, vector<vector<int>>& travelScore)
{
const long long INF = 1e18;
long long f[K + 1][n];
for (int i = 0; i <= K; i++) for (int j = 0; j < n; j++) f[i][j] = -INF;
for (int j = 0; j < n; j++) f[0][j] = 0;
for (int i = 1; i <= K; i++)
for (int j = 0; j < n; j++) {
// 旅客第 i 天留在城市 j
f[i][j] = f[i - 1][j] + stayScore[i - 1][j];
// 旅客第 i 天从城市 jj 移动到城市 j
for (int jj = 0; jj < n; jj++)
if (j != jj) f[i][j] = max(f[i][j], f[i - 1][jj] + travelScore[jj][j]);
}
long long ans = 0;
for (int j = 0; j < n; j++) ans = max(ans, f[K][j]);
return ans;
}
};
