动态规划dp

  动态规划就是对递归的优化,防止递归的时间复杂度太高,用空间换时间。状态方程就是思考递归的过程。

题目大意:

五个海盗ABCDE按照顺序依次提出对于100个金币如何分的方案,如果一个人的方案没有被通过,他就会被打死,问最后每个人获得多少金币?

题目大意:

一个村子,i个人,每个人只能一收一寄,求多少种方法
f(1)=0   f(2)=1  f(3)=2
f(i)=(i-1) * ( f(i-2) + f(i-1) )   

从左往右模型

从左往右模型(1)

题目大意:

1代表A,2代表B...,11代表AA或者K,111代表AAA或者AK或者KA,给一组字符串,问有多少种转化的方法

/*调用时F(string ,0);
第一位怎么转化,第二位怎么转化...
前两位怎么转化,第三位怎么转化...
...
str[0...i-1]已经转化完了,剩下的怎么转化
0~i-1已经转化完成,i.....n有多少种转化结果

*/
int  F(string s,int i){
    if(i=str.length())    return 1;
//第一,如果为空,则结果自增1 ,第二,如果转化完成,则结果自增1
    if(s[i]=='0')      return 0;
    if(s[i]=='1'){
        int res=F(s,i+1);
        if(i+1<s.length())     res+=F(s,i+2);
        return res;
    }
    if(s[i]=='2'){
        int res=F(s,i+1);
        if(i+1<s.length()  &&  ( s[i+1]>='0' && s[i+1]<='6')  )     res+=F(s,i+2);
        return res;
    }
    return F(s,i+1);
}

从左往右模型(2)

题目大意:

  给你每一个东西的重量w和价值v放在两个数组内,给你一个袋子最大能放多少重量bag,求能装上的最大价值(01背包问题)

c++//暴力怼法
/*
al表示0~i-1之间已经做完选择,目前已经达到的重量是多少
返回-1表示没有方案
*/
int F(int i , int al , int bag){
    if( al > bag )    return -1;
    if( i==w.length() )    return 0;
    //两种选择:要或者不要
    int p1=F(i+1 , al , bag);
    int p2next=F(i+1 , a1+w[i] , bag);
    int p2=-1;
    if(p2next != -1){//如果不是无效的
        p2=v[i] + p2next;
    }
    retuen max(p1,p2);
}





/*
rest表示只剩下这些空间,返回能获得的最大值
主函数调用时,F( 0 , bag )
*/
int F(int i , int rest){动态规划
    if( rest<=0 )    return 0;
    if( i == w.length() )    return 0;
    int p1=F( i+1 , rest );
    int p2=F( i+1 , rest-w[i] );
}







//动态规划求法
//返回能够获得的最大价值
//  调用dp( 0 , bag )
int dp( int i , int rest ){
      int dp[n+1][bag+1]={0};
      for( int i=n-1 ; i>=0 ; i-- ){
            for( int rest=0 ; rest<=bag ; rest++ ){
                  dp [i] [rest]  =  dp [i+1] [rest]
                  if(  rest >=w[i]   ){//如果可以装
                       dp[i][rest]= max(   dp [i] [rest]  ,  v[i] + dp [i+1]]  [rest-w[i] ]  )
                       //面临两种选择:不装  或者  装
                  } 
                  
            }
      }
      return dp [0] [bag];
}

范围上尝试的模型

范围上尝试的模型(1)

题目大意:

arr表示一组牌,AB两个人依次拿最左或者最右的牌,AB绝顶聪明,返回胜利者的分数
例如:70 100 1 4
A:4     100=104返回
B:70    4=74

/*
*/
int Xian( int i , int j ){
      if( i == j )    return a[i];
      return max( a[i]+Xian( i+1 , j ) , a[j]+Hou( i , j-1) );
}
int Hou( int i , int j ){
      if( i == j )    return 0;
      return min( Xian( i+1 , j ) , Xian( i , j-1 ) );
}

范围上尝试的模型(2)

题目大意:

N皇后问题,N * N的格子,摆放的皇后不同行不同列,不同斜线,求方法数

/*
arr数组表示第i行中的皇后放在了第几列
一共n行
返回值1-i不用管,后面的有对少摆种

*/
int  F(int i){
      if( i== n )     return 1;
      int res=0;
      for( int j=0 ; j<n; j++ ){
          if( is(i,j)  ){//如果合法
              r[i]=j;
              res+=F(i+1);
          }
      }
      return res;
}


/*
(a,b)和(c,d)共斜线的条件
     | a-c |   ==   | b-d |
*/

bool is( int i , int  j ){
      for( int k=0 ; k<i ; k++ ){
            //k  arr[k]       i  j
            if( j == arr[k]  ||  abs(arr[k]-j) == abs(i-k))   return false;
      }
      return true;
}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值