題目在這個OJ上可以送出:http://simpleoj.cn/index.php/home/problem/pro_info/id/86.html
交換瓶子
有N個瓶子,編号 1 ~ N,放在架子上。
比如有5個瓶子:
2 1 3 5 4
要求每次拿起2個瓶子,交換它們的位置。
經過若幹次後,使得瓶子的序号為:
1 2 3 4 5
對于這麼簡單的情況,顯然,至少需要交換2次就可以複位。
如果瓶子更多呢?你可以通過程式設計來解決。
輸入格式為兩行:
第一行: 一個正整數N(N<10000), 表示瓶子的數目
第二行:N個正整數,用空格分開,表示瓶子目前的排列情況。
輸出資料為一行一個正整數,表示至少交換多少次,才能完成排序。
例如,輸入:
5
3 1 2 5 4
程式應該輸出:
3
再例如,輸入:
5
5 4 3 2 1
程式應該輸出:
2
資源約定:
峰值記憶體消耗 < 256M
CPU消耗 < 1000ms
請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入…” 的多餘内容。
所有代碼放在同一個源檔案中,調試通過後,拷貝送出該源碼。
注意: main函數需要傳回0
注意: 隻使用ANSI C/ANSI C++ 标準,不要調用依賴于編譯環境或作業系統的特殊函數。
注意: 所有依賴的函數必須明确地在源檔案中 #include , 不能通過工程設定而省略常用頭檔案。
送出時,注意選擇所期望的編譯器類型。
【思路分析】首先把這些東西排好序,而且要交換的次數最少,那麼非選擇排序不可,因為選擇排序是每次在剩餘的所有數中尋找一個最小的放在最先面,這樣的話可以保證交換次數最少。而且這個題的這n個瓶子大小是從1到n,那麼我們可以用”桶“的的形式來記錄大小為i的瓶子的位置所在,然後再進行交換就簡單了。
【AC代碼】
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
#define LL long long
#define PI acos(-1.0)
int a[],book[];//book[i]記錄的大小為i的瓶子的位置
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=; i<=n; i++)
{
scanf("%d",&a[i]);//大小為a[i]的瓶子的位置為i
book[a[i]]=i;
}
int sum=;
for(int i=; i<=n; i++)
{
if(i!=a[i])//第i個位置放置的一定是大小為i的瓶子,這裡采用的是選擇排序的思想
{
sum++;
int x=book[i];//第i個瓶子的位置
int temp=a[x];
a[x]=a[i];
book[a[i]]=x;
a[i]=temp;
book[i]=i;
}
}
printf("%d\n",sum);
}
return ;
}