万恶的期末考试---算法复习---递归与分治策略(二分搜索与大数乘法与矩阵对角线相加,strassen矩阵乘法,棋盘覆盖)

已经考过三科了,还有三科,明天下午就要考算法了,心慌慌,抓紧写个博客做算法复习,静静心

呃呃呃  说好的只是复习下,自己拓展到了天外 ,第二章还没结束....代码如下

大数乘法过程如下:

二分搜索与大数乘法与矩阵对角线相加

package chap2_dgfz;

import java.util.Collections;

public class Z2 {

    public static void main(String[] args) {
//        int a[]={1,2,3,4};
//        int x=3;
//        int n=a.length;
//        System.out.println(binarySearch(a,x,n));
        
        int []a={8,2,1,6,5,4,7};
        int []b={9,6,7,8,5};
//        int []b={9,1};
        dscf(a,b);
        
    }
    
    /**
     *  二分搜索技术
     * 将n个元素分成个数大致相同的两半 a[n/2]==x a[n/2]<x  a[n/2]>x
     * 
     * 查询的值是x,查询的列表是a[],列表大小是n
     * 返回x在a[]中的下标
     * */
    public static int binarySearch(int []a,int x,int n){
        int left=0;int right=n-1;
        while(left<=right){
            int middle=(left+right)/2;
            if(x==a[middle]) return middle;
            if(x>a[middle]) left=middle+1;
            else right=middle-1;
        }
        return -1;
    }
    /**
     * 大数乘法
     * 印象中在大二上学过数据结构中用数组进行大数计算,具体的忘了....
     * 课本没有具体例子,在csdn借鉴https://blog.csdn.net/tjsinor2008/article/details/5625849
     * 以8216547*96785举例  使用列表法 ①一位一位的列表 ②三位三位的列表
     * 
     * a[]是第一个大数       b[]是第二个大数
     * 
     * bl是行 al是列
     * **/
    public static void dscf(int []a,int []b){
        int al=a.length,bl=b.length;
        int res1[][] = new int[bl][al];
        for(int i=0;i<bl;i++){
            for(int j=0;j<al;j++){
                res1[i][j]=b[i]*a[j];
            }
        }
        
        for(int i=0;i<bl;i++){
            for(int j=0;j<al;j++){
                System.out.print(res1[i][j]+" ");
            }
            System.out.println();
        }
        djxxj(res1,al,bl);
        
        
        
        int[]num=new int[al+bl-1];
        int x=bl-1;
        int y=al-1;
        
        int jw=0;//进位
        int tsum=0;//暂时存储的和
        
        for(int i=al+bl-2;i>=0;i--){
                if(x>=0){
                for(int m=x,n=al-1;n>=y&&m<=bl-1;m++,n--){
                    System.out.println(m+","+n);
                    tsum+=res1[m][n];
                }
                tsum+=jw;
                num[i]=tsum%10;
                jw=tsum/10;
                System.out.println("num:  "+tsum);
                tsum=0;
                x--;
                y--;
                System.out.println(i+"~~~!!!"+num[i]);
                System.out.println("jw:  "+jw);
                System.out.println("x,y:"+x+","+y);
                System.out.println();
                }else{
                    if(x==-1){y=al-2;}
                    
                    for(int m=0,n=y;n>=0&&m<=bl-1;m++,n--){
                        System.out.println(m+","+n);
                        tsum+=res1[m][n];
                    }
                    tsum+=jw;
                    if(y==0){
                        num[i]=tsum;
                    }else{
                    num[i]=tsum%10;}
                    jw=tsum/10;
                    System.out.println("num:  "+tsum);
                    tsum=0;
                    y--;
                    x=-2;
                    System.out.println(i+"~~~====="+num[i]);
                    System.out.println("jw:  "+jw);
                    System.out.println("x,y:"+x+","+y);
                    System.out.println();
                    
            }
        }
        
        for(int i=0;i<al+bl-1;i++){
            System.out.print(num[i]);
        }
    }
    /**
     * 对角线加法,列数大于等于行数
     * 由上面的函数推导而来
     * bl为行数 al为列数
     * **/
    public static void djxxj(int [][]res1,int al,int bl){
        
        int[]num=new int[al+bl-1];
        int tsum=0;//暂时存储的和
        int x=bl-1;
        int y=al-1;
        for(int i=al+bl-2;i>=0;i--){
            if(x>=0){
            for(int m=x,n=al-1;n>=y&&m<=bl-1;m++,n--){
                System.out.println(m+","+n);
                tsum+=res1[m][n];
                System.out.println(tsum);
            }
            num[i]=tsum;
            tsum=0;
            x--;
            y--;
            }else{
                if(x==-1){y=al-2;}
                
                for(int m=0,n=y;n>=0&&m<=bl-1;m++,n--){
                    System.out.println(m+","+n);
                    tsum+=res1[m][n];
                }
                if(y==0){
                    num[i]=tsum;
                }else{
                num[i]=tsum;}
                System.out.println("num:  "+tsum);
                tsum=0;
                y--;
                x=-2;
                
        }
    }
        
        System.out.println("对角线求和结果");
        for(int i=0;i<al+bl-1;i++){
            System.out.print(num[i]+" ");
        }
        System.out.println();
    }
}

stressen矩阵乘法

把每个矩阵分割为4份,然后创建如下10个中间矩阵:

S1 = B12 - B22
S2 = A11 + A12
S3 = A21 + A22
S4 = B21 - B11
S5 = A11 + A22
S6 = B11 + B22
S7 = A12 - A22
S8 = B21 + B22
S9 = A11 - A21
S10 = B11 + B12

接着,计算7次矩阵乘法:

P1 = A11 • S1
P2 = S2 • B22
P3 = S3 • B11
P4 = A22 • S4
P5 = S5 • S6
P6 = S7 • S8
P7 = S9 • S10

最后,根据这7个结果就可以计算出C矩阵:
C11 = P5 + P4 - P2 + P6
C12 = P1 + P2
C21 = P3 + P4
C22 = P5 + P1 - P3 - P7

棋盘覆盖

package chap2_dgfz;

public class ChessBoard {
        int tile=1;//表示L型骨牌的编号
        int[][] board = new int[4][4];//表示棋盘
        /**
         * 处理带有特殊棋子的棋盘.tr、tc表示棋盘的入口即左上角的行列号,dr、dc表示特殊棋子的行列位置,size表示棋盘的行数或者列数
         * */
        public void chessBoard(int tr, int tc, int dr, int dc, int size)
        {
            if(size == 1) return;
            int t = tile++;
            System.out.println(t);
            int s = size/2;//每一次化大棋盘为一半的子棋盘
            //要处理带有特殊棋子的棋盘,第一步先处理左上棋盘
            if(dr < tr + s && dc< tc + s)//左上角子棋盘有特殊棋子
                chessBoard(tr,tc,dr,dc,s);//处理有特殊棋子的左上角子棋盘
            else//处理无特殊棋子的左上角子棋盘
            {
                board[tr+s-1][tc+s-1] = t;
                //设左上角子棋盘的右下角为特殊棋子,用t型的骨牌覆盖。由于骨牌有三种,当处理过程中同一级设置的特殊棋子用相同的骨牌覆盖
                chessBoard(tr,tc,tr+s-1,tc+s-1, s);//处理有用骨牌覆盖的格子作为特殊棋子的左上角子棋盘
            }
            
            //第二步处理右上角棋盘
            if(dr < tr+s && dc >=tc+s)//右上角子棋盘有特殊棋子
            {
                chessBoard(tr,tc+s,dr,dc,s);//处理有特殊棋子的右上角子棋盘
            }    
            else
            {
                board[tr+s-1][tc+s] =t;//设右上角子棋盘的左下角为特殊棋子,用t型的骨牌覆盖。由于骨牌有三种,当处理过程中同一级设置的特殊棋子用相同的骨牌覆盖
                chessBoard(tr,tc+s,tr+s-1,tc+s,s);//处理有用骨牌覆盖的格子作为特殊棋子的右上角子棋盘
            }
            
            //第三步处理左下角子棋盘
            if(dr >=tr+s && dc<tc+s)//左下角子棋盘有特殊棋子
            {
                chessBoard(tr+s,tc,dr,dc,s);//处理有特殊棋子的左下角子棋盘
            }
            else
            {
                board[tr+s][tc+s-1] = t;//设左下角子棋盘的右上角为特殊棋子,用t型的骨牌覆盖。由于骨牌有三种,当处理过程中同一级设置的特殊棋子用相同的骨牌覆盖
                chessBoard(tr+s,tc,tr+s,tc+s-1,s);//处理有用骨牌覆盖的格子作为特殊棋子的左下角子棋盘
            }
            
            //第四步处理右下角棋盘
            if(dr>=tr+s&& dc>= tc+s)//右下角子棋盘有特殊棋子
            {  
                chessBoard(tr+s,tc+s,dr,dc,s);//处理有特殊棋子的右下角子棋盘
            }
            else
            {
                board[tr+s][tc+s] = t;//设子棋盘右下角的左上角为特殊棋子,用t型的骨牌覆盖。由于骨牌有三种,当处理过程中同一级设置的特殊棋子用相同的骨牌覆盖
                chessBoard(tr+s,tc+s,tr+s,tc+s,s);//处理有用 骨牌覆盖的格子作为特殊棋子的右下角子棋盘
            }
        }
        
        public static void main(String[] args)
        {
            ChessBoard c = new ChessBoard();
            c.chessBoard(0,0,2,1,4);
            for(int i = 0; i <4; i++)
            {    for(int j = 0; j <4; j++)
                    System.out.print(c.board[i][j]+"  ");
            System.out.println();
            }
        }
    }
 

猜你喜欢

转载自blog.csdn.net/qq_39065788/article/details/85724832
今日推荐