动态规划:
动态规划问题基本特征:
- 问题具有多阶段决策的特征。
- 每一阶段都有相应的“状态”与之对应,描述状态的量称为“状态变量”。
- 每一阶段都面临一个决策,选择不同的决策将会导致下一阶段不同的状态。
- 每一阶段的最优解问题可以递归地归结为下一阶段各个可能状态的最优解问题,各子问题与原问题具有完全相同的结构。
动态规划问题概念:
- 阶段:据空间顺序或时间顺序对问题的求解划分阶段。
- 状态:描述事物的性质,不同事物有不同的性质,因而用不同的状态来刻画。对问题的求解状态的描述是分阶段的。
- 决策:根据题意要求,对每个阶段所做出的某种选择性操作。
状态转移方程:用数学公式描述与阶段相关的状态间的演变规律。
解题步骤:
1、判断问题是否具有最优子结构性质,若不具备则不能用动态规划。
2、把问题分成若干个子问题(分阶段)。
3、建立状态转移方程(递推公式)。
4、找出边界条件。
5、将已知边界值带入方程。
6、递推求解。
例题:
#include<cstdio>
#include<string>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 2010;
int dp[1050];
int mp[1050][1050];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<=i;j++)
cin>>mp[i][j];
memset(dp,0,sizeof(dp));
for(int i=n-1;i>=0;i--)
for(int j=0;j<=i;j++)
dp[j]=max(dp[j],dp[j+1])+mp[i][j];
cout<<dp[0];
return 0;
}
拓展内容:
位运算:
含义 | C语言 |
---|---|
按位与 | a & b |
按位或 | a |
按位异或 | a ^ b |
按位取反 | ~a |
左移 | a << b |
带符号右移 | a >> b |
无符号右移 | / |
优先级顺序:
- ~
- << 、 >>
- &
- ^
- |
- &=、^=、|=、<<=、>>=
位运算的具体描述:
按位与概念:
通常用于二进制的取位操作,例如一个数 and 1的结果就是取二进制的最末位。
相同位的两个数字都为1,则为1;若有一个不为1,则为0。
用法:
判断一个整数的奇偶,二进制的最末位为0表示该数为偶数,最末位为1表示该数为奇数。
#include<cstdio>
#include<string>
#include<algorithm>
#include<math.h>
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
int main()
{
int n;
while(cin>>n)
{
if(n&1)
cout<<"奇数"<<endl;
else cout<<"偶数"<<endl;
}
}
输出结果如下:
训练部分题解:
思路:若有偶数,找第一个小于最后一位的偶数数字交换。若没有小于最后一位的偶数,最后一个偶数与最后一位进行交换。若没有找到。如果每位数都是奇数,输出-1。
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<iostream>
const int M=1e5+6;
char s[M],t;
using namespace std;
int main()
{
long long int length,k=-1;
cin>>s;
length=strlen(s);
for (int i=length-2;i>=0;i--)
{
if ((s[i]-'0')%2==0)
{
if (k==-1)
k=i;
else
if (s[i]<s[length-1])
k=i;
}
}
if (k==-1)
cout<<-1<<endl;//当不存在偶数数据时
else
{
t=s[k];
s[k]=s[length-1];
s[length-1]=t;
cout<<s<<endl;
}
return 0;
}
总结:
按位与操作可用于今后的判断奇偶性中。