动态规划就是对递归的优化,防止递归的时间复杂度太高,用空间换时间。状态方程就是思考递归的过程。
题目大意:
五个海盗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;
}