河南省第二届ACM程序设计大赛解题报告(置换群)
1.
1 /* 2 前两道题一直在纠结提议,特别是第二题,看了别人的代码才明白过来题意,由测试用例都没明白 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 //假设边界在AB之间 15 int solve() 16 { 17 /* 18 刚开始忘记了开标记数组,要保证每个节点只访问一次,否则会死循环 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 //头结点也要申请空间 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 求最小费用时求较小着:用分解后的每个循环里的最小值,或者全局最小值 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 //若分解后的循环里面只有一个元素,则该元素在原来的群里面必定是排好序的 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;//循环的长度 30 //vis数组标记的是输入的顺序,先找到第一个后,那么经过下面的操作后第一个循环就被全部标记过了 31 while(vis[i]) 32 { 33 i++; 34 } 35 int begin = i; 36 int sum = 0;//每次循环的所有元素和 37 //找循环 38 /* 39 必须用 do while(至少执行一次),或者死循环里用break;不可while(i!=begin)这样的话 因为int begin = i则大循环一直执行 40 */ 41 do 42 { 43 length++; 44 vis[i] = true;//i是个下标值 ,放在i改变之前 45 if(l_min>a[i]) 46 l_min = a[i]; 47 sum += a[i]; 48 //hash数组返回的只是一个下标值 49 i = hash[b[i]];//返回的是起点对应的下标所对应元素的下标 ,必须放在sum之后 50 }while(begin!=i); 51 52 len -= length;//必须在continue之前 53 if(length==1)//必须有 ,表示循环里只有一个元素,则不花费代价 54 continue; 55 56 //ans1用的是循环内最小值,sum存的是循环内所有的元素和 ,局部最小元素用了 (length-1)次,其他的用了一次,因为在sum 57 //里已经加了一次局部最小,所以 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;//是累计,不是直接赋值 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];//排好序的数组 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 }
作者:火星十一郎
本文版权归作者火星十一郎所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.