zoukankan      html  css  js  c++  java
  • 算法(一)

    动态规划

    一、递归

    #include<iostream>
    #include<string>
    using namespace std;
    
    int n; 
    int Hanoi(int n)
    {
    	if(n==1)
    	{
    		return 1;
    	}
    	else
    	{
    	  return  2*Hanoi(n-1)+1;
    	}
    }
    int main()
    {
    	int n=3;
    	cout<<Hanoi(n); 
    }
    

     

     2、递推

    #include<iostream>
    #include<string>
    using namespace std;
    const int Max=64;
    int h[Max]={0};
    int main()
    {
    	int n;
    	cin>>n;
    	h[1]=1;
    	for(int i=2;i<=n;i++)
    	{
    		h[i]=h[i-1]*2+1;
    	}
    	cout<<h[n]<<endl;
    }
    

     

    二、 

    1、二维数组的定义

    #include<iostream>
    #include<algorithm>
    #define Max 101
    using namespace std;
    int D[Max][Max];
    int n;
    //int MaxSum(int i,int j)
    
    int main()
    {
    	int n;
    	cin>>n;
    	for(int i=0;i<n;i++)
    	{
    		for(int j=0;j<=i;j++)
    		    cin>>D[i][j];
    	}
    	for(int i=0;i<n;i++)
    	{
    		for(int j=0;j<=i;j++)
    		    cout<<D[i][j]<<" ";
    		cout<<endl;
    	}
    	
    }
    

    2、

    #include<iostream>
    #include<algorithm>
    #define Max 101
    using namespace std;
    int D[Max][Max];//输入初始矩阵图 
    int n;//全局变量 
    int s=0;
    int MaxSum(int i,int j)//i,j 到底部的最大距离
    {
    	if(i==n)//边界条件,到底部时,等于本身
    	{
    		return D[i][j];
    	} 
    	else
    	{
    		return D[i][j]+max(MaxSum(i+1,j),MaxSum(i+1,j+1));//返回位置到底部的最大距离,自己值,加上次求解的最大值。
    	}
    } 
    
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		    cin>>D[i][j];
    	}
    	cout<<endl;
    	cout<<MaxSum(1,1);
    	//5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
    }
    

    因为是三角形,所有情况就都会通过递归搜索得到。

    3、

     

    #include<iostream>
    #include<algorithm>
    #define MAX 101
    
    using namespace std;
    int D[MAX][MAX];//输入初始矩阵图 
    int n;//全局变量 
    int s=0;
    int maxSum[MAX][MAX];
    
    int MaxSum(int i,int j) //i,j位置的数到最底层的最大距离 
    {
    	if(maxSum[i][j]!=-1)
    	    return maxSum[i][j];
    	else
    	{    
    		if(i==n)//到最底层时,距离就是本身 
    		{
    			maxSum[i][j]=D[i][j];
    		} 
    		else
    		{
    			maxSum[i][j]=D[i][j]+max(MaxSum(i+1,j),MaxSum(i+1,j+1));	
    		}
    		return maxSum[i][j];
        }	
    } 
    
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    		    cin>>D[i][j];
    		    maxSum[i][j]=-1;
    	    }
    	}
    	cout<<endl;
    	MaxSum(1,1);
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    		    cout<<maxSum[i][j]<<" ";
    	    }
    	    cout<<endl;
    	}
    	//cout<<MaxSum(1,1);
    //	cout<<s;
    	//5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
    }
    

     

    将各个位置的距离记录下来,省去一次次的迭代。可以极大效率的提高运行速度,注意这里不能每次只存最大量,需要保存所有的值。

    4、看到上面记录表,可以考虑将递归改为递推,不用重复迭代那么多次。  

    #include<iostream>
    #include<algorithm>
    #define MAX 101
    
    using namespace std;
    int D[MAX][MAX];//输入初始矩阵图 
    int n;//全局变量 
    int maxSum[MAX][MAX];
    
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    		    cin>>D[i][j];
    	    }
    	}
    	for(int i=1;i<=n;i++)
    	{
    		maxSum[n][i]=D[n][i];//最后一行赋值 
    	}
    	for(int i=n-1;i>=1;i--)
    	{
    		for(int j=1;j<=i;j++)
    	        maxSum[i][j]=D[i][j]+max(D[i+1][j],D[i+1][j+1]);//	
    	} 
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    		    cout<<maxSum[i][j]<<" ";
    	    }
    	    cout<<endl;
    	}
    	//cout<<MaxSum(1,1);
    //	cout<<s;
    	//5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
    }
    

    出错的原因是混淆了递推加的是变化后的值,而不是初始值。

    #include<iostream>
    #include<algorithm>
    #define MAX 101
    
    using namespace std;
    int D[MAX][MAX];//输入初始矩阵图 
    int n;//全局变量 
    int maxSum[MAX][MAX];
    
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    		    cin>>D[i][j];
    	    }
    	}
    	for(int i=1;i<=n;i++)
    	{
    		maxSum[n][i]=D[n][i];//最后一行赋值 
    	}
    	for(int i=n-1;i>=1;i--)
    	{
    		for(int j=1;j<=i;j++)
    	        maxSum[i][j]=D[i][j]+max(maxSum[i+1][j],maxSum[i+1][j+1]);//比较的是新的数组	
    	} 
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    		    cout<<maxSum[i][j]<<" ";
    	    }
    	    cout<<endl;
    	}
    	//cout<<MaxSum(1,1);
    //	cout<<s;
    	//5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
    }
    

    5、空间优化

    #include<iostream>
    #include<algorithm>
    #define MAX 101
    
    using namespace std;
    int D[MAX][MAX];//输入初始矩阵图 
    int n;//全局变量 
    int *maxSum;
    
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=i;j++)
    		{
    		    cin>>D[i][j];
    	    }
    	}
        maxSum=D[n];//指向第n行 
    	for(int i=n-1;i>=1;i--)
    	{
    		for(int j=1;j<=i;j++)
    	        maxSum[j]=D[i][j]+max(maxSum[j],maxSum[j+1]);//比较的是新的数组	
    	} 
        for(int i=1;i<=n;i++)
    	    cout<<maxSum[i]<<" "; 
    	//cout<<MaxSum(1,1);
    //	cout<<s;
    	//5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
    }
    

    三、

    1、错误实例

    #include<iostream>//错误实例
    #include<algorithm>
    
    using namespace std;
    const int Maxn=1010;
    int a[Maxn];
    int maxLen[Maxn];
    int main()
    {
    	int n;
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		cin>>a[i];
    		maxLen[i]=1;
    	}
    	for(int i=2;i<=n;i++)
    	{
    		for(int j=1;j<=i-1;j++)
    		{
    			if(i=2&&a[j]<=a[i])
    			{
    				maxLen[i]++;
    				break;
    			}
    			else if(a[j]<=a[i]&&a[j]>a[j-1])
    			{
    				maxLen[i]++;
    			}
    		}
    		cout<<maxLen[i]<<" ";
    		
    	}
    	cout<<endl;
    	int Max=maxLen[1]; 
    	for(int i=1;i<=n;i++)
    	{
    		if(maxLen[i]>Max)
    		    Max=maxLen[i];
    	}
    	cout<<Max;
    	//7 1 7 3 5 9 4 8
    }
    

    上面这段程序是错误的,错误的根源是没有理解清楚该如何递推,只是单纯的比较,并没有归纳到将前一次的比较运用到这次来。  

     2、

    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    const int Maxn=1010;
    int a[Maxn];
    int maxLen[Maxn];
    int main()
    {
    	int n;
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		cin>>a[i];
    		maxLen[i]=1;
    	}
    	for(int i=2;i<=n;i++)
    	{
    		for(int j=1;j<=i-1;j++)
    		{
    			if(a[i]>=a[j])
    			    maxLen[i]=max(maxLen[i],maxLen[j]+1);//从小于i的数每个都比较,如果大于,说明上升子序列可以加1,最后比较多组,找出最大的
    		}
    		cout<<maxLen[i]<<" ";	
    	}
    	cout<<endl;
    	int Max=maxLen[1]; 
    	for(int i=1;i<=n;i++)
    	{
    		if(maxLen[i]>Max)
    		    Max=maxLen[i];
    	}
    	cout<<Max;
    	//7 1 7 3 5 9 4 8
    }
    

    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    const int Maxn=1010;
    int a[Maxn];
    int maxLen[Maxn];
    int main()
    {
    	int n;
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		cin>>a[i];
    		maxLen[i]=1;
    	}
    	for(int i=2;i<=n;i++)
    	{
    		for(int j=1;j<=i-1;j++)
    		{
    			if(a[i]>=a[j])
    			    maxLen[i]=max(maxLen[i],maxLen[j]+1);
    		}
    		cout<<maxLen[i]<<" ";	
    	}
    	cout<<endl;
    	cout<<*max_element(maxLen+1,maxLen+n+1);//新的找最大值的方法
    	//7 1 7 3 5 9 4 8
    }

    3、最大最小值

    #include<iostream>  
    #include<algorithm>  
    using namespace std;  
      
    bool cmp(int a,int b)  
    {  
        return a<b;  
    }  
    int main()  
    {  
        int num[]={2,3,1,6,4,5};  
        cout<<"最小值是 "<<*min_element(num,num+6)<<endl;  
        cout<<"最大值是 "<<*max_element(num,num+6)<<endl;  
        cout<<"最小值是 "<<*min_element(num,num+6,cmp)<<endl;  
        cout<<"最大值是 "<<*max_element(num,num+6,cmp)<<endl;  
        return 0;   
    }  
    

    s、

    四、

    #include<iostream>
    #include<cstring>
    using namespace std;
    const int Max=64;
    char sz1[1000],sz2[1000];
    int maxLen[1000][1000];
    int main()
    {
    	while(cin>>sz1>>sz2)
    	{
    		int l1=strlen(sz1);
    		int l2=strlen(sz2);
    		int ntmp;
    		for(int i=0;i<=l1;i++)//边界条件,0代表空串 
    	        maxLen[i][0]=0;
    	    for(int j=0;j<=l2;j++)
    	        maxLen[0][j]=0;
    	    for(int i=1;i<=l1;i++)
    		{
    			for(int j=1;j<=l2;j++)
    			{
    				if(sz1[i-1]==sz2[j-1])
    				    maxLen[i][j]=maxLen[i-1][j-1]+1;//i,j 都加1 
    				else
    				    maxLen[i][j]=max(maxLen[i][j-1],maxLen[i-1][j]);
    			}
    		}
    		for(int i=0;i<=l1;i++)
    		{
    		   for(int j=0;j<=l2;j++)
    	        {
    		       cout<<maxLen[i][j]<<" ";
    		    }
    			cout<<endl; 
    	    }
    		cout<<maxLen[l1][l2]<<endl; 
    	}
    	// abcfbc abfcab
    }
    

    0的存在是边界,整个矩阵可以看出并不是对称矩阵,所以else的判断条件尤为重要。

    五、

    #include <iostream>  
    #include <cstdio>  
    #include <cstring>  
      
    using namespace std;  
    const int maxn=1000;  
    const int inf=0x3f3f3f3f;  
    int n;  
    char c[maxn];  
    int dp[maxn][maxn];  
    int num[maxn][maxn];  
    int m;  
      
    int NUM(int x,int y) //从x位置到y位置的数 
    {  
        if(num[x][y]!=-1)  
        {  
            return num[x][y];  
        }  
        int sum=0;  
        for(int i=x;i<y;i++)  
        {  
            sum=sum*10+c[i]-'0';  
        }  
        num[x][y]=sum;  
        return sum;  
    }  
    int DP(int p,int x) //p个字符,x个加号; 
    {  
        if(dp[p][x]!=-1)  //一开始是等于-1;不等于-1说明计算过了 
        {  
            return dp[p][x];  
        }  
      
        if(x==0) //没有加号 
        {  
            dp[p][0]=NUM(0,p);  //字符串变数字 
            return dp[p][0];  
        }  
        dp[p][x]=inf;  
        for(int k=p-1;k>=x;k--)//k会发生变化,控制加号可能出现的位置。大于x是为了给加号留够位置。 
        {  
            dp[p][x]=min(dp[p][x],DP(k,x-1)+NUM(k,p));//dp在多次循环比较中找到最小的 !循环递归化 
        }  
        return dp[p][x];   
    }  
      
    int main() 
    {    
        while(cin>>c)//输入字符  
        {  
            memset(dp,-1,sizeof(dp)); //全部赋为-1; 
            memset(num,-1,sizeof(num));  
            scanf("%d",&m);  //输入加号个数 
            n=strlen(c);  
            printf("%d
    ",DP(n,m)); //n个字符,m个加号 
        }  
        return 0;  
    }  
    

    #include<iostream>
    #include<string>
    #include<cstring>
    using namespace std;
    
    const int Max=100;
    const int N=20;
    const int inf=0x3f3f3f3f;
    int mindit[Max][N];//存放Max个字符,N个加号 ,最小值 
    int n;
    int L;
    string str;
    
    int Num(int x,int y)//k位置到L位置 
    {
    	int sum=0;  
    	for(int i=x;i<y;i++)  
    	{  
    	    sum=sum*10+str[i]-'0';  
    	}  
    	return sum;  
        
    }
    
    int MinDit(int P,int x)
    {
        if(mindit[P][x]!=-1)
    	    return mindit[P][x];
    	else if(x==0)//边界条件的核心 
    	{
    		return Num(0,P);
    	}
    	   
    	else
    	{
    		mindit[P][x]=inf;
    		for(int k=P-1;k>=x;k--)
    		{
    			mindit[P][x]=min(mindit[P][x],MinDit(k,x-1)+Num(k,P));
    		}
    		return mindit[P][x];
        }	
    }
    
    int main()
    {
    	getline(cin,str);//数字符串 
    	cin>>n;//加号个数 
    	memset(mindit,-1,sizeof(mindit));//二维数组赋值同样值方式 
    	L=str.length();
    	cout<<MinDit(L,n)<<endl;
    }
    

    换用string 和去掉和的求解空间。

    六、

    1、递归

    #include<iostream>  
    #include<cstring>  
    #include<algorithm>  
    using namespace std;  
      
    //递归方法,求解最长回文子序列  
    int lps(char *str, int i, int j) //字符串i和j之间的回文字符长度 
    {  
        if (i == j)  
            return 1;   //只有一个元素,回文长度为1  
        if (i > j) 
    	    return 0;   //因为只计算序列str[i....j]  
        //如果首尾相同  
        if (str[i] == str[j])  
            return lps(str, i + 1, j - 1) + 2;  
        //如果首尾不同  
        else
    	    return max(lps(str, i, j - 1), lps(str, i + 1, j));  
    }  
      
    int main()  
    {  
        char str[] = "cabbeaf";  
        int n = strlen(str);  
        int res = lps(str, 0, n-1);  
        cout << res<< endl;  
        return 0;  
    }  

    2、

    #include<iostream>  
    #include<cstring>  
    #include<algorithm>  
    using namespace std;
    const int Maxn=100; 
    int Len[Maxn][Maxn]; 
      
    //递归方法,求解最长回文子序列  ,自下而上 
    int lps(char *str, int n) //字符串i和j之间的回文字符长度 
    {  
        memset(Len,0,sizeof(Len));//赋值 Len[i][j]是i和j位置处的回文长度 
        int temp;
        for(int i=0;i<n;i++)
        {
        	Len[i][i]=1;//1个长度 
    	}
    	for(int i=1;i<n;i++)
    	{
    	    for(int j=0;j+i<n;j++)
    		{
    			if(str[j+i]==str[j])
    			{
    				Len[j][j+i]=Len[j+1][j+i-1]+2;//初设值为0,才对 
    			}
    			else
    			{
    			    Len[j][j+i]=max(Len[j+1][j+i],Len[j][j+i-1]);	
    			} 
    		}	
    	} 
    	return Len[0][n-1];
    }  
      
    int main()  
    {  
        char str[] = "cabbeaf"; 
        int n = strlen(str);  
        int res = lps(str,n);  
        cout << res<< endl;  
        return 0;  
    }  
    

    动态规划的思想就是用矩阵记录迭代的值,不用重复迭代,关键是如何循环给矩阵赋值。该题就是从小到大的间距给矩阵赋值,使得下次的赋值能用上次的赋值。

    3、求解回文数的个数

    #include <bits/stdc++.h>
     
    using namespace std;
    typedef long long LL;
    const int maxn = 50 + 5;
    LL dp[maxn][maxn];
    char s[maxn];
    
    int main() 
    {
        scanf("%s", s + 1);
        int len = strlen(s + 1);
        memset (dp, 0, sizeof(dp));//初值为0; 
        for(int i = 1; i <= len; i++)
    	{
            for(int l = 1; l + i - 1 <= len; l++) 
    		{
                int r = l + i - 1;//dp[1][1],dp[2][2],dp[3][3]
                                //dp[1][2],dp[2][3]
                dp[l][r] += dp[l + 1][r];
                dp[l][r] += dp[l][r - 1];
                if (s[l] == s[r]) 
    			    dp[l][r] += 1;
                else 
    			    dp[l][r] -= dp[l + 1][r - 1];
            }
        }
        printf ("%lld
    ", dp[1][len]);
        return 0;
    }

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

      

  • 相关阅读:
    (二十)WebGIS中图层树功能的设计和实现
    WebGIS中矢量切图的初步研究
    百度兴趣点下载工具设计和实现
    服务端常规知识详解
    Shp数据批量导入Postgresql工具的原理和设计
    浅谈C#中一种类插件系统编写的简单方法(插件间、插件宿主间本身不需要通信)
    从底层开发谈WebGIS中实现地理长度固定的可视窗口的思路和方法
    用存储过程判断某个人员在一天的行进轨迹中是否有超过指定时间的停留
    Linux启动与禁止SSH用户及IP的登录
    JVM中的垃圾回收
  • 原文地址:https://www.cnblogs.com/ruo-li-suo-yi/p/8778352.html
Copyright © 2011-2022 走看看