河南省第二届ACM程序设计大赛解题报告(置换群)
生活随笔
收集整理的這篇文章主要介紹了
河南省第二届ACM程序设计大赛解题报告(置换群)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1.
1 /* 2 前兩道題一直在糾結(jié)提議,特別是第二題,看了別人的代碼才明白過來題意,由測試用例都沒明白 3 */ 4 #include <iostream> 5 #include <cstring> 6 #include <queue> 7 using namespace std; 8 9 const int maxn = 55; 10 int ins[maxn]; 11 bool vis[maxn] = {false}; 12 int N,A,B; 13 14 //假設(shè)邊界在AB之間 15 int solve() 16 { 17 /* 18 剛開始忘記了開標(biāo)記數(shù)組,要保證每個(gè)節(jié)點(diǎn)只訪問一次,否則會死循環(huán) 19 */ 20 int a = max(A,B); 21 int b = min(A,B); 22 queue <int > q; 23 int cnt = 0; 24 while(!q.empty()) 25 q.pop(); 26 q.push(A); 27 vis[A] = true; 28 bool flag = false; 29 while(!q.empty()) 30 { 31 cnt++; 32 int head = q.front(); 33 q.pop(); 34 int left = head - ins[head]; 35 int right = head + ins[head]; 36 if(left>=b&&!vis[left]) 37 { 38 if(left==B) 39 { 40 flag = true; 41 break; 42 } 43 vis[left] = true; 44 q.push(left); 45 } 46 if(right<=a&&!vis[right]) 47 { 48 if(right==B) 49 { 50 flag = true; 51 break; 52 } 53 vis[right] = true; 54 q.push(right); 55 } 56 } 57 if(flag) 58 return cnt; 59 else 60 return -1; 61 } 62 63 int main() 64 { 65 int i,j,k; 66 int M; 67 68 cin>>M; 69 while(M--) 70 { 71 memset(vis,false,sizeof(vis)); 72 memset(ins,0,sizeof(ins)); 73 74 cin>>N>>A>>B; 75 for(i=1; i<=N; i++) 76 { 77 cin>>ins[i]; 78 } 79 int ans = solve(); 80 cout<<ans<<endl; 81 } 82 return 0; 83 84 }
2.剛開始用list寫的,太惡心了,寫不成,就換成直接的鏈表了
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 5 int N,K; 6 typedef struct Node 7 { 8 int data; 9 Node * next; 10 }Node; 11 12 Node *head; 13 void init() 14 { 15 //頭結(jié)點(diǎn)也要申請空間 16 head = new Node; 17 head->data = 0; 18 head->next = NULL; 19 //頭插法 20 for(int i=1; i<=N; i++) 21 { 22 Node *p = new Node; 23 p->next = head->next; 24 head->next = p; 25 p->data = N-i+1; 26 } 27 } 28 29 int main() 30 { 31 int i,j,k; 32 cin>>N>>K; 33 int a,b,c; 34 init(); 35 for(i=1; i<=K; i++) 36 { 37 cin>>a>>b>>c; 38 Node *p,*q,*r; 39 Node *temp1, *temp2, *temp3; 40 41 int cnt = 0; 42 for(p=head; cnt<a-1; cnt++,p=p->next); 43 temp1 = p; 44 45 cnt = 0; 46 for(p=head; cnt<b; cnt++,p=p->next); 47 temp2 = p; 48 49 cnt = 0; 50 for(p=head; cnt<c; cnt++,p=p->next); 51 temp3 = p; 52 53 Node *temp4 = temp2->next; 54 temp2->next = temp3->next; 55 temp3->next = temp1->next; 56 temp1->next = temp4; 57 } 58 Node *p; 59 int cnt = 0; 60 for(p=head->next,cnt=0; cnt<10; cnt++,p=p->next) 61 { 62 cout<<p->data<<endl; 63 64 } 65 while(1); 66 return 0; 67 }
3.
4.參考華杰做出來的
?
1 //置換群問題 2 /* 3 求最小費(fèi)用時(shí)求較小著:用分解后的每個(gè)循環(huán)里的最小值,或者全局最小值 4 */ 5 #include <iostream> 6 #include <cstring> 7 #include <cstdlib> 8 #include <algorithm> 9 using namespace std; 10 11 const int maxn = 1010; 12 int N; 13 int g_min = 1010;//全局置換群最小值,題目上說最大高度是1000 ,每次的全局最小會改變,不能是const 14 15 int hash[maxn],a[maxn],b[maxn]; 16 bool vis[maxn]; 17 18 int solve() 19 { 20 memset(vis,false,sizeof(vis)); 21 int i,j,k; 22 //若分解后的循環(huán)里面只有一個(gè)元素,則該元素在原來的群里面必定是排好序的 23 int len = N; 24 int l_min = 1010;//局部最小值 25 int ans = 0; 26 while(len>0) 27 { 28 int i = 0; 29 int length = 0;//循環(huán)的長度 30 //vis數(shù)組標(biāo)記的是輸入的順序,先找到第一個(gè)后,那么經(jīng)過下面的操作后第一個(gè)循環(huán)就被全部標(biāo)記過了 31 while(vis[i]) 32 { 33 i++; 34 } 35 int begin = i; 36 int sum = 0;//每次循環(huán)的所有元素和 37 //找循環(huán) 38 /* 39 必須用 do while(至少執(zhí)行一次),或者死循環(huán)里用break;不可while(i!=begin)這樣的話 因?yàn)閕nt begin = i則大循環(huán)一直執(zhí)行 40 */ 41 do 42 { 43 length++; 44 vis[i] = true;//i是個(gè)下標(biāo)值 ,放在i改變之前 45 if(l_min>a[i]) 46 l_min = a[i]; 47 sum += a[i]; 48 //hash數(shù)組返回的只是一個(gè)下標(biāo)值 49 i = hash[b[i]];//返回的是起點(diǎn)對應(yīng)的下標(biāo)所對應(yīng)元素的下標(biāo) ,必須放在sum之后 50 }while(begin!=i); 51 52 len -= length;//必須在continue之前 53 if(length==1)//必須有 ,表示循環(huán)里只有一個(gè)元素,則不花費(fèi)代價(jià) 54 continue; 55 56 //ans1用的是循環(huán)內(nèi)最小值,sum存的是循環(huán)內(nèi)所有的元素和 ,局部最小元素用了 (length-1)次,其他的用了一次,因?yàn)樵趕um 57 //里已經(jīng)加了一次局部最小,所以 length-2)*l_min; 58 int ans1 = sum + (length-2)*l_min; 59 //全局的先把局部的換出來最后還要在換回來 ,所以答案是兩次全局 + 兩次局部 + sum里除了局部之外的其他元素和 60 int ans2 = sum + l_min + (length+1)*g_min; 61 62 ans += ans1>ans2?ans2:ans1;//是累計(jì),不是直接賦值 63 } 64 return ans; 65 } 66 67 int main() 68 { 69 int i,j,k; 70 int T; 71 cin>>T; 72 while(T--) 73 { 74 cin>>N; 75 memset(hash,0,sizeof(hash)); 76 memset(a,0,sizeof(a)); 77 memset(b,0,sizeof(b)); 78 79 80 for(i=0; i<N; i++) 81 { 82 cin>>a[i]; 83 b[i] = a[i];//排好序的數(shù)組 84 if(g_min>a[i]) 85 { 86 g_min = a[i]; 87 } 88 hash[a[i]] = i; 89 } 90 sort(b,b+N); 91 int ans = solve(); 92 cout<<ans<<endl; 93 } 94 system("pause"); 95 return 0; 96 }
?
轉(zhuǎn)載于:https://www.cnblogs.com/hxsyl/archive/2013/04/25/3043678.html
總結(jié)
以上是生活随笔為你收集整理的河南省第二届ACM程序设计大赛解题报告(置换群)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《梦仙》第二十一句是什么
- 下一篇: 通过正则表达式查找一个模式的所有实例