1. 程式人生 > >uva10570 Meeting with Aliens

uva10570 Meeting with Aliens

uva 統計 情況 對稱 names 序列 sca scan 所在

先證明把每次i放到i位置最後次數最少:感覺,可以,用歸納法?

//在序列後再加一個相同的序列,就可以模擬用各個數字開頭的情況了
每個位置不對的只需要換一次
54123 ,5固定->41235變成12345

任何一個數固定不變,都相當於從這種情況對應的1所在的位置開始排一遍12345.(例如54123 ,5固定->41235變成12345)所以只需要每個位置開始都判斷變成12345所需步數即可

把輸入倒過來看,變成12345就相當於正著變成54321 (這個對稱很巧妙啊),可以模塊化

#include <cstdio>
#include <algorithm>
using
namespace std; int cal(int A[], int N) { //54123—>12345可以看做12354->12345所以每個位置開始都判斷變成12345所需步數即可 int cnt = 0, vis[505] = {0}; for (int i = 1; i <= N; i++) //cnt統計不用換位的個數;不用換位的A[j]就等於j,進入下一個數了 if(!vis[i]) { //某個數還沒到正確位置 cnt++; for (int j = i; !vis[j]; j = A[j]) //
這個循環中一直換位直到不用換 vis[j] = 1; } return N - cnt; } int main() { int N, A[1010], B[1010]; while (scanf("%d", &N), N) { for (int i = 1; i <= N; i++) { scanf("%d", &A[i]); B[N - i + 1] = B[2 * N - i + 1] = A[i + N] = A[i]; }
int ans = 1 << 30; for (int i = 0; i < N; i++) ans = min(ans, cal(A + i, N)); for (int i = 0; i < N; i++) ans = min(ans, cal(B + i, N)); printf("%d\n", ans); } return 0; } #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 505; int p[N],k[N],w[N]; int f[N],n; int solve(int s, int d) { int cnt = 0; for(int i = 1; i <= n; i++) { if(k[i] != s) { cnt++; k[w[s]] = k[i]; w[k[i]] = w[s]; k[i] = s; w[s] = i; } s += d; if(s > n) s = 1; if(s <= 0) s = n; } return cnt; } int main() { while(scanf("%d",&n) && n) { for(int i = 1; i <= n; i++) { scanf("%d",&p[i]); f[p[i]] = i; } int Min = 0x3f3f3f3f; for(int i = 1; i <= n; i++) { memcpy(k, p, sizeof(p)); memcpy(w, f, sizeof(f)); Min = min(Min, solve(i,-1)); memcpy(k, p, sizeof(p)); memcpy(w, f, sizeof(f)); Min = min(Min, solve(i,1)); } printf("%d\n",Min); } }

uva10570 Meeting with Aliens