题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805403651522560
贪心算法的题大多都是要有一个最佳策略的,这就导致不知道策略的人很难写出正确答案,这道题一定要注意一下,虽然代码不长。

策略

最核心的一步是用0所在的pos[i] 与i交换

代码

  1. #include<vector>
  2. #include<algorithm>
  3. #include<iostream>
  4. using namespace std;
  5. int main(){
  6. int N, left = 0;
  7. int ans = 0;
  8. scanf("%d",&N);
  9. vector<int> a(N), pos(N);//
  10. for(int i = 0; i < N; i++){
  11. scanf("%d",&a[i]);
  12. pos[a[i]] = i;
  13. if(a[i]!=i&&a[i]!=0)left++;
  14. }
  15. int k = 1;
  16. while(left>0){
  17. if(pos[0] == 0){
  18. while(k < N){
  19. if(pos[k]!=k){
  20. swap(pos[0],pos[k]);
  21. ans++;
  22. break;
  23. }
  24. k++;
  25. }
  26. }
  27. while(pos[0]!=0){
  28. swap(pos[0],pos[pos[0]]);//将0和pos[0]交换
  29. ans++;
  30. left--;
  31. }
  32. }
  33. printf("%d",ans);
  34. return 0;
  35. }

柳的代码:https://www.liuchuo.net/archives/2301
不使用left记录,使代码更简洁,当哨兵回到自己位置的时候,交换一次

  1. #include <iostream>
  2. using namespace std;
  3. int main() {
  4. int n, t, cnt = 0, a[100010];
  5. cin >> n;
  6. for(int i = 0; i < n; i++){
  7. cin >> t;
  8. a[t] = i;
  9. }
  10. for(int i = 1; i < n; i++) {
  11. if(i != a[i]) {
  12. while(a[0] != 0) {
  13. swap(a[0],a[a[0]]);
  14. cnt++;
  15. }
  16. if(i != a[i]) {
  17. swap(a[0],a[i]);
  18. cnt++;
  19. }
  20. }
  21. }
  22. cout << cnt;
  23. return 0;
  24. }