分治演算法思想(4)未——兩個大數相乘,歐冠冠軍盃比賽日程安排
阿新 • • 發佈:2019-01-25
(1)分治演算法基礎解題一般步驟:1.分解,將要解決的問題劃分成若干規模較小的同類問題2.求解,當子問題劃分的足夠小時,用較簡單的方法解決3.合併,按原問題的要求,將子問題的解逐層合併構成原問題的解此方法主要是對分治的理解,以及結果的調整和對結果的合併。較難理解~需仔細思考(2)實踐1.解決”大數相乘“問題即計算兩個大數的積;例如123*456分析:sorry?程式設計程式碼如下:
3 4 1 2
4 3 2 1編碼如下:
#include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> char *result='\0'; int pr=1; void getFill(char *a,char *b,int ia,int ja,int ib,int jb,int tbool,int move) { int r,m,n,s,j,t; char *stack; m=a[ia]-48; if(tbool) { //直接將結果陣列的標誌位填入,棧對思想 r=(jb-ib>ja-ia)?(jb-ib):(ja-ia); stack=(char *)malloc(r+4); for(r=j=0, s=jb; s>=ib; r++,s--) { n=b[s]-48; stack[r]=(m*n+j)%10; j=(m*n+j)/10; } if(j) { stack[r]=j; r++; } for(r--; r>=0; r--,pr++) result[pr]=stack[r]; free(stack); for(move=move+pr; pr<move; pr++) result[pr]='\0'; } else { r=pr-move-1; for(s=jb,j=0; s>=ib; r--,s--) { n=b[s]-48; t=m*n+j+result[r]; result[r]=t%10; j=t/10; } for(;j;r--) { t=j+result[r]; result[r]=t%10; j=t/10; } } } int get(char *a,char *b,int ia,int ja,int ib,int jb,int t,int move) { int m,n,s,j; if(ia==ja) { getFill(a,b,ia,ja,ib,jb,t,move); return 1; } else if (ib==jb) { getFill(b,a,ib,jb,ia,ja,t,move); return 1; } else { m=(ja+ia)/2; n=(jb+ib)/2; s=ja-m; j=jb-n; get(a,b,ia,m,ib,n,t,s+j+move); get(a,b,ia,m,n+1,jb,0,s+move); get(a,b,m+1,ja,ib,n,0,j+move); get(a,b,m+1,ja,n+1,jb,0,0+move); } return 0; } int main() { char *a,*b; int n,flag; a=(char *)malloc(1000); b=(char *)malloc(1000); printf("The program will computer a*b\n "); printf("Enter a,b:"); scanf("%s %s",a,b); result=(char *)malloc(strlen(a)+strlen(b)+2); flag=pr=1; result[0]='\0'; if(a[0]=='-'&&b[0]=='-') { get(a,b,1,strlen(a)-1,1,strlen(b)-1,1,0); } if(a[0]=='-'&&b[0]!='-') { flag=0; get(a,b,1,strlen(a)-1,0,strlen(b)-1,1,0); } if(a[0]!='-'&&b[0]=='-') { flag=0; get(a,b,0,strlen(a)-1,1,strlen(b)-1,1,0); } if(a[0]!='-'&&b[0]!='-') { get(a,b,0,strlen(a)-1,0,strlen(b)-1,1,0); } if(!flag) printf("-"); if(result[0]) printf("%d",result[0]); for(n=1; n<pr; n++) { printf("%d",result[n]); } printf("\n"); free(a); free(b); free(result); system("pause"); return 0; }
(2)歐冠冠軍盃比賽日程安排設共有n隊參加,初賽進行n-1天,每隊要和其他各隊進行一場比賽,然後按照最後積分選拔進入決賽的球隊,要求沒隊每天進行一場比賽,並且不能輪空,按上述要求安排比賽日程決定每隊每天的對手。
分析:分治演算法得——先將所有隊伍分成兩半,則n隊的比賽日程表可以通過n/2個隊的比賽日程決定。然後繼續按上述方法將一半再分成一半隻到只剩餘最後兩隊結束/例如四隊:編號 第一天1 2 3 42 1 4 33 4 1 2
4 3 2 1編碼如下:
#include <stdio.h> #include <stdlib.h> #define MAXN 64 int a[MAXN+1][MAXN+1]={0}; void gamecal(int k,int n)//處理編號k開始的n個球隊的過程 { int i,j; if(n==2) { a[k][1]=k;//參賽球隊編號 a[k][2]=k+1;//對陣球隊編號 a[k+1][1]=k+1;//參賽球隊編號 a[k+1][2]=k;//對陣球隊編號 } else { gamecal(k,n/2); gamecal(k+n/2,n/2); for(i=k;i<k+n/2;i++) { for(j=n/2+1;j<=n;j++) { a[i][j]=a[i+n/2][j-n/2]; } } for(i=k+n/2;i<k;i++) { for(j=n/2;j<=n;j++) { a[i][j]=a[i-n/2][j-n/2]; } } } } int main() { int m,i,j; printf("參賽球隊數:"); scanf("%d",&m); j=2; for(i=2;i<8;i++) { j=j*2; if(j==m) break; } if(i>=8) { printf("參賽球隊書必須為2的整數次冪,並且不超過64!\n"); getch(); return 0; } gamecal(1,m); printf("\n編號"); for(i=2;i<=m;i++) { printf("%2d天",i-1); printf("\n"); for(i=1;i<m;i++) { for(j=1;j<=m;j++) printf("%4d",a[i][j]); printf("\n"); } } getch(); return 0; }