您的位置:首页 > 其它

51Nod1574(新姿势:使序列有序的最小交换次数)

2017-08-27 20:11 429 查看
这个题按自己写的超时了,看了大神博客学习一种新姿势。
http://blog.csdn.net/f_zyj/article/details/72286343
*
* 交换任意两数的本质是改变了元素位置,
* 故建立元素与其目标状态应放置位置的映射关系
*/
int getMinSwaps(vector<int> &A)
{
// 排序
vector<int> B(A);
sort(B.begin(), B.end());
map<int, int> m;
int len = (int)A.size();
for (int i = 0; i < len; i++)
{
m[B[i]] = i; // 建立每个元素与其应放位置的映射关系
}

int loops = 0; // 循环节个数
vector<bool> flag(len, false);
// 找出循环节的个数
for (int i = 0; i < len; i++)
{
if (!flag[i])
{
int j = i;
while (!flag[j])
{
flag[j] = true;
j = m[A[j]]; // 原序列中j位置的元素在有序序列中的位置
}
loops++;
}
}
return len - loops;
}

vector<int> nums;

int main()
{
nums.push_back(1);
nums.push_back(2);
nums.push_back(4);
nums.push_back(3);
nums.push_back(5);

int res = getMinSwaps(nums);

cout << res << '\n';

return 0;
}然后这个题就按这个算法变一下就行了
#include<cstdio>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200000+10;
int p[maxn];
int pos[maxn];
int vis[maxn];
int Scan()
{
int res = 0, ch, flag = 0;

if((ch = getchar()) == '-') //判断正负
flag = 1;

else if(ch >= '0' && ch <= '9') //得到完整的数
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9' )
res = res * 10 + ch - '0';

return flag ? -res : res;
}
int main()
{
int n,a;
n = Scan();
for(int i=1;i<=n;i++) p[i] = Scan() ;
for(int i=1;i<=n;i++) {
a = Scan() ;
pos[a] = i;
}
for(int i=1;i<=n;i++)
p[i] = pos[p[i]];
long long sum = 0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
if(vis[i]) continue;
long long res = 0;
for(int j=i;!vis[j];j=p[j])
{
res += abs(j-p[j]);
vis[j] = 1;
}
sum += res/2;
}
printf("%lld\n",sum);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐