置换群
poj 3270 Cow Sorting 简单的更换
如果初始状态是
a:2 3 1 5 4 6
则目标状态为
b:1 2 3 4 5 6且下标为初始状态中的3 1 2 4 5 6(a[3],a[1]...)
将置换群写成循环的形式
(2,3,1),(5,4),6就不用移动了。
移动方式2种
1:选循环内最小的数和其它len-1个数交换
2:选整个序列最小的数和循环内最小的数交换。转到1。再换回来。
#include<cstdio> #include<queue> #include<algorithm> #include<cstring> using namespace std; int a[100005],b[100005]; int hash[100005]; bool vis[100005]; int main() { int n; while(~scanf("%d",&n)) { memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+1+n); for(int i=1;i<=n;i++) hash[a[i]]=i; int ans=0; /* 2 3 1 1 2 3----id: 3 1 2 */ for(int i=1;i<=n;i++) { if(vis[i]||a[i]==b[i]) continue; int id=i,x=a[i],len=0,mins=0x3f3f3f3f,sum=0; while(true) { sum+=x; mins=min(mins,x); vis[id]=true; x=b[id]; id=hash[b[id]]; len++; if(x==a[i]) break; } ans+=min(sum-mins+mins*(len-1),(sum-mins+b[1]*(len-1)+2*(b[1]+mins))); } printf("%d\n",ans); } return 0; }
i位置相应a[i]位置。求相应K次之后的字符串是什么,(k非常大)
相同和上题一样暴力寻找置换循环。比如
4 5 3 7 2 8 1 6 10 9 可分成(4,7,1),(5,2),(3),(8,6),(10,9),找到了每块循环的长度len之后
对每块循环模拟求k%len次即可了。
代码有点不同,但思想就是这样。
#include<cstdio> #include<queue> #include<algorithm> #include<cstring> #include<vector> using namespace std; int a[205]; int sum[205]; char str[205]; char tmp[205]; int v[205][205]; int main() { int cas,n,k; while(scanf("%d",&n)!=EOF&&n) { for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=0; for(int i=1;i<=n;i++) { int j=a[i]; if(i==j) {v[i][sum[i]++]=i;continue;} v[i][sum[i]++]=i; while(i!=j) { v[i][sum[i]++]=j; j=a[j]; } } while(~scanf("%d",&k)&&k) { getchar(); gets(str+1); for(int i=strlen(str+1)+1;i<=n;i++) str[i]=' '; for(int i=1;i<=n;i++) tmp[ v[i][k%sum[i]] ]=str[i]; tmp[n+1]='\0'; puts(tmp+1); } puts(""); } return 0; }
版权声明:本文博主原创文章。博客,未经同意不得转载。