#include <iostream>
#include <algorithm>
using namespace std;
static const int MAX=1000;
static const int VMAX=10000;
int A[100],B[100],T[100];
bool V[100];
int solve(int N,int s)
{
int ans=0;
sort(B,B+N);
for(int i=0;i<N;i++) T[B[i]]=i;//记录排序后的数组,其各个元素所对应的下标
for(int i=0;i<N;i++)
{
if(V[i]) continue;
int S=0;
int cur=i;
int m=INT_MAX;
int tot=0;
while(1)
{
V[cur]=true;
tot++;
int v=A[cur];
S+=v;
m=min(m,v);
cur=T[v];
if(V[cur]) break;
}
ans+=min(S+(tot-2)*m,m+S+(tot+1)*s);
}
return ans;
}
int main()
{
int N,s=INT_MAX;
cin>>N;
for(int i=0;i<N;i++)
{
cin>>A[i];
B[i]=A[i];
V[i]=false;
s=min(s,A[i]);
}
cout<<N<<endl;
int ans=solve(N,s);
cout<<ans<<endl;
return 0;
#include <algorithm>
using namespace std;
static const int MAX=1000;
static const int VMAX=10000;
int A[100],B[100],T[100];
bool V[100];
int solve(int N,int s)
{
int ans=0;
sort(B,B+N);
for(int i=0;i<N;i++) T[B[i]]=i;//记录排序后的数组,其各个元素所对应的下标
for(int i=0;i<N;i++)
{
if(V[i]) continue;
int S=0;
int cur=i;
int m=INT_MAX;
int tot=0;
while(1)
{
V[cur]=true;
tot++;
int v=A[cur];
S+=v;
m=min(m,v);
cur=T[v];
if(V[cur]) break;
}
ans+=min(S+(tot-2)*m,m+S+(tot+1)*s);
}
return ans;
}
int main()
{
int N,s=INT_MAX;
cin>>N;
for(int i=0;i<N;i++)
{
cin>>A[i];
B[i]=A[i];
V[i]=false;
s=min(s,A[i]);
}
cout<<N<<endl;
int ans=solve(N,s);
cout<<ans<<endl;
return 0;
}
总结:本问题一共设计了四个数组,其中B数组为A数组的拷贝,T数组可以理解为一个“映射”数组。所谓的映射是什么意思呢,就是建立元素及其下标关系的映射数组,这里学到一个技巧,就是通过数组来建立类似python中的“键值”对的元素映射关系。V数组用来记录某个元素是否被访问过,总之,这个题目给我的收获很大,以后要时常复习。