在线编程(三)

来源:互联网 发布:mac安装windows系统 编辑:程序博客网 时间:2024/05/02 20:37

1.斐波那契数列
思路1:直接递归调用,时间复杂度 O(2N)

int Fibonacci(int n){if(n==1 || n==2)return n;return Fibonacci(n-1) + Fibonacci(n-2);}

思路2:动态规划,将前n次的结果保存,时间复杂度O(N)

int Fibonacci(int n){if(n==1 || n==2)return n;int now=1;int pre=1;for(int i=2;i<n;i++){now=now+pre;    pre=now-pre;}return now;}

思路3:F(n)=F(n1)+F(n2
可以写成矩阵的形式:
(F(n),F(n1))=(F(n1),F(n2))[1110]

由上式可以得到:

(F(n),F(n1))=(F(2),F(1))[1110]n2

//注:懒得换编译器,还是用的vs2008,一些C++11的特性不支持,矩阵赋值比较繁琐,可以考虑重写个矩阵的类,重载=vector<vector<int>>  multMatrix(vector<vector<int>> a,vector<vector<int>> b)//矩阵乘法{    int temp=0;    vector<int> tmp;    vector<vector<int>> res;    for(int i=0;i<a.size();i++)//m    {        for(int j=0;j<b[0].size();j++)//n        {            for(int k=0;k<a[0].size();k++)//n            {                temp+=a[i][k]*b[k][j];                          }            tmp.push_back(temp);            temp=0;        }        res.push_back(tmp);        tmp.clear();    }    return res;}vector<vector<int>> powerN(vector<vector<int>> a,int n)//矩阵的n次方,这里直接写了2*2的单位阵{    vector<vector<int>> tmp;    vector<vector<int>> sum;    vector<int> temp;    temp.push_back(a[0][0]);    temp.push_back(a[0][1]);    tmp.push_back(temp);    temp.clear();    temp.push_back(a[1][0]);    temp.push_back(a[1][1]);    tmp.push_back(temp);    temp.clear();    temp.push_back(1);    temp.push_back(0);    sum.push_back(temp);    temp.clear();    temp.push_back(0);    temp.push_back(1);    sum.push_back(temp);    int m=1;    while(n!=0)    {        if((n&1)!=0)        {            sum=multMatrix(sum,tmp);        }        tmp=multMatrix(tmp,tmp);        n=n>>1;     }    return sum;}int Fibonacci(int n){    if(n==1 || n==2)        return 1;    vector<vector<int>> a;    vector<vector<int>> b;    vector<int> temp;    temp.push_back(1);    temp.push_back(1);    a.push_back(temp);    temp.clear();    temp.push_back(1);    temp.push_back(0);    a.push_back(temp);    b= powerN(a,n-2);    return b[0][0]+b[1][0]; }

类似的问题还有:台阶问题(初始值不同),牛的繁殖问题F(n)=F(n1)+F(n3

2.矩阵的最小路径和:给定一个矩阵,从矩阵的左上角开始,每次向下或向右,最后到达右下角的位置,路径上的所有数字加起来就是路径和。
思路:dp[i][j]存储从左上角到达m[i][j]的最小路径,第一行和第一列的数即为该列/该列到该位置的和。从m[0][0]到m[i][j]的路径必经过m[i][j-1]或m[i-1][j],d[i][j]=min{d[i-1][j],d[i][j-1]}+m[i][j]

int minPath(vector<vector<int>> m){    vector<vector<int>> dp;    dp.resize(m.size());    for(int i=0;i<m.size();i++)        dp[i].resize(m[0].size());    dp[0][0]=m[0][0];    for(int j=1;j<m[0].size();j++)        dp[0][j]=dp[0][j-1]+m[0][j];    for(int i=1;i<m.size();i++)        dp[i][0]=dp[i-1][0]+m[i][0];    for(int i=1;i<m.size();i++)        for(int j=1;j<m.size();j++)        {            dp[i][j]=min(dp[i-1][j],dp[i][j-1])+m[i][j];        }    return dp[m.size()-1][m[0].size()-1];}

思路2:减少空间复杂度的一种算法,如果列数大于行数,则从左往右更新数组,如果行数大于列数,则从上往下更新

int minPath2(vector<vector<int>> m){    vector<int> dp;    int more=max(m.size(),m[0].size());    int less=min(m.size(),m[0].size());    bool rowmore=more==m.size();//如果rowmore==1 说明行数大于列数    dp.resize(less);    dp[0]=m[0][0];    for(int i=1;i<less;i++)        dp[i]=dp[i-1]+(rowmore?m[0][i]:m[i][0]);    for(int i=1;i<more;i++)    {        dp[0]=dp[0]+(rowmore?m[i][0]:m[0][i]);        for(int j=1;j<less;j++)            dp[j]=min(dp[j],dp[j-1])+(rowmore?m[i][j]:m[j][i]);    }    return dp[less-1];}

3.换钱的最少货币:定义一个数组,表示货币的面值,每种货币不限数目,再给定一个值aim表示要换的钱,给出一个表示aim的最少货币数。

变:换钱的方法数

#include <iostream>#include <vector>using namespace std;/**************************暴力递归**************/ int process1(vector<int> arr,int index,int aim) {     int res=0;     if (index==arr.size())         res=aim==0?1:0;     else     {         for(int i=0;arr[index]*i<=aim;i++)         res+=process1(arr,index+1,aim-arr[index]*i);     }     return res; }int coins1(vector<int> arr,int aim){    if(arr.size()==0 || aim==0)        return 0;    return  process1(arr,0,aim);}/*********************************************************/ /****************************记忆搜索*********************/ //时间复杂度O(N*aim^2) int process2(vector<int> arr,int index,int aim,vector<vector<int>> &map) {     int res=0;     int mapvalue;     if (index==arr.size())         res=aim==0?1:0;     else     {         for(int i=0;arr[index]*i<=aim;i++)         {             mapvalue=map[index+1][aim-arr[index]*i];             if(mapvalue!=0)             {                 res+=mapvalue==-1?0:mapvalue;             }             else             {                 res+=process2(arr,index+1,aim-arr[index]*i,map);             }         }     }     map[index][aim]=res==0?-1:res;     return res; } int coins2(vector<int> arr,int aim) {    vector<vector <int> > map(arr.size()+1 ,vector<int>(aim+1));    if(arr.size()==0 || aim==0)        return 0;    return  process2(arr,0,aim,map); }/*********************************************************/ /****************************动态规划*********************/ //时间复杂度O(N*aim^2) int coins3(vector<int> arr,int aim) {     int n=arr.size();     vector<vector<int>> dp(n,vector<int>(aim+1));     for(int i=0;i<n;i++)     {         dp[i][0]=1;     }     for(int j=0;j<=aim;j++)     {         if(j%arr[0]==0)         {             dp[0][j]=1;         }         else         {             dp[0][j]=INT_MAX;         }     }     int res=0;     for(int i=1;i<n;i++)         for(int j=1;j<=aim;j++)         {             for(int k=0;j-arr[i]*k >=0;k++)             {                 if(dp[i-1][j-arr[i]*k]!=INT_MAX)                    res+=dp[i-1][j-arr[i]*k];             }             dp[i][j]=res;             res=0;         }         return dp[n-1][aim]; }/*********************************************************/ /****************************动态规划2*********************///时间复杂度O(N*aim) int coins4(vector<int> arr,int aim) {     int n=arr.size();     vector<vector<int>> dp(n,vector<int>(aim+1));     for(int i=0;i<n;i++)     {         dp[i][0]=1;     }     for(int j=0;j<=aim;j++)     {         if(j%arr[0]==0)         {             dp[0][j]=1;         }         else         {             dp[0][j]=INT_MAX;         }     }     int res=0;     for(int i=1;i<n;i++)         for(int j=1;j<=aim;j++)         {             res=dp[i-1][j];             if(j-arr[i]>=0 && dp[i][j-arr[i]]!=INT_MAX)                 if(res!=INT_MAX)                   res+=dp[i][j-arr[i]];                 else                    res=dp[i][j-arr[i]];             dp[i][j]=res;             res=0;         }         return dp[n-1][aim]; }int main(){    vector<int> arr;    arr.push_back(5);    arr.push_back(10);    arr.push_back(25);    arr.push_back(1);    int aim=15;//  int res1=coins1(arr,aim);//   cout<<res1<<endl;//  int res2=coins2(arr,aim);//  cout<<res2<<endl;//  int res3=coins3(arr,aim);//  cout<<res3<<endl;    int res4=coins4(arr,aim);    cout<<res4<<endl;    return 0;}
原创粉丝点击