//伪代码
输入:n,s[n],f[n],v[n]
排序:根据f[n]
计算:p[n]
int computeOpt(int j){
if(j==0)
return 0;
else
return max(v[j]+computeOpt(p[j]),computeOpt(j-1));
}
分析:分层递归调用,时间复杂度指数级增长。
解决:存储每个子问题的计算结果,以备查找之需。
//伪代码. O(nlogn) time |
输入:n,s[n],f[n],v[n];
排序:根据f[n];//O(nlogn)
计算:p[n];
定义:m[n], m[0]=0;
int mComputeOpt(int j){
//每次调用O(1) time ,总共O(n) time
if(m[j] is empty)
m[j]=max( v[j]+mComputeOpt(p[j]) , mComputeOpt(j-1) );
return m[j];
}
分析:时间复杂度O(nlogn),若已由开始时间、结束时间排序O(n)。
findSolution(int j){
if(j==0)
return {
};
else if(v[j]+m[p[j]]>m[j-1])
return {
j} ∪ findSolution(p[j]);
else
return findSolution(j-1);
}
分析:由于递归调用次数<=n ,因此时间复杂度为O(n)。
//伪代码
bottomUp(int n,int s[],int f[],int v[]){
sort(f[n]);
compute p[n];
int m[n];m[0]=0;
for(int i=1;i<=n;i++)
m[i]=max( v[i]+m[p[j]] , m[i-1] );
}
#include
#include
#include
#include
using namespace std;
const int maxn = 205;
struct Job
{
int s, e, v, index;
Job(int s=0,int e=0,int v=0,int index=0)//构造函数特有语法,比=效率高,有默认参数
:s(s), e(e), v(v), index(index)
{
}
}job[maxn];
int p[maxn], m[maxn];//p记录job j前第一个不冲突的job i;m记录job 1,2..j的max value
bool cmpE(Job a, Job b)
{
return a.e < b.e;//将job 结束时间从小到大排序
}
int main()
{
//读入数据&初始化
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
memset(p, 0, sizeof(p));
memset(m, 0, sizeof(m));
int n; cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> job[i].s >> job[i].e >> job[i].v;
job[i].index = i;
}
//处理:1.排序 2. 计算p 3.计算 m
//1.
sort(job, job + n, cmpE);
//2.
for (int i = n; i >0 ; i--)
{
for (int j = n - 1; j > 0;j--)
if (job[i].s >= job[j].e)
{
p[i] = job[j].index;
break;
}
}
//3.
for (int i = 1; i <= n; i++)
{
m[i] = max(job[i].v + m[p[i]], m[i - 1]);
}
//输出:m[n] 即max value of n jobs
cout << m[n] << endl;
return 0;
}
selectedLeastSquares(int n,int p[n],int c){
for(int j=1;j<=n;j++)
for(int i=1;i<=j;i++)
计算e(i,j);
int m[maxn];m[0]=0;
for(int j=1;j<=n;j++)
m[j]=min{
eij+c+m[i-1]} ,1<=i<=j
return m[n]
}
//bottom-up
//O(n*W) time | O(n*W) space
int knapsack(int n,int W,int w[n],int v[n]){
int OPT[maxn][maxn];
//OPT(i,w)=0;if(i==0)
for(int j=0;j<=W;j++)
OPT[0][j]=0;
//OPT(i,w)=OPT(i-1,w);if(w
//OPT(i,w)=max( v[i]+OPT(i-1,w-wi) , OPT(i-1,w));else
for(int i=1;i<=n;i++){
for(int j=1;j<=W;j++){
if(w[i]>j)
OPT[i][j]=OPT[i-1][j];
else
OPT[i][j]=max( v[i]+OPT[i-1][j-w[i]] , OPT[i-1][j]);
}
}
return OPT[n][W];
}
//伪代码
int sequenceAlignment(int m,int n,int x[m],int y[n],int δ[],int α[][]){
//if j=0
for(int i=0;i<m;i++)
OPT[i,0]=δ[xi];
//if i=0
for(int j=0;j<n;j++)
OPT[0,j]=δ[yj];
//otherwise
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
OPT[i][j]=min(α[xi][yi]+OPT[i-1][j-1],δ[xi]+OPT[i-1][j],δ[yj]+OPT[i][j+1]);
}
}
return OPT[m][n];
}
#include
#include
#include
#include
#include
using namespace std;
#define maxn 105
int dp[maxn][maxn];
int M[maxn][maxn];
//题目中的 scoring matrix
void matrix(){
M['A']['A'] = M['C']['C'] = M['G']['G'] = M['T']['T'] = 5;
M['A']['C'] = M['C']['A'] = M['A']['T'] = M['T']['A'] = -1;
M['-']['T'] = M['T']['-'] = -1;
M['A']['G'] = M['G']['A'] = M['C']['T'] = M['T']['C'] = -2;
M['T']['G'] = M['G']['T'] = M['-']['G'] = M['G']['-'] = -2;
M['C']['G'] = M['G']['C'] = M['-']['A'] = M['A']['-'] = -3;
M['-']['C'] = M['C']['-'] = -4;
}
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
matrix();
int t; cin >> t;
while (t--){
//初始化&读入
char s1[maxn], s2[maxn];
int len1, len2;
cin >> len1 >> s1+1; cin >> len2 >> s2+1;//将字符串输入到s1中,且从s1[1]开始输入
//scanf("%d %s", &len2, s2 + 1);
//处理
dp[0][0] = 0;
for (int i = 1; i <= len1; i++)
dp[i][0] = dp[i - 1][0] + M[s1[i]]['-'];
for (int j = 1; j <= len2; j++)
dp[0][j] = dp[0][j - 1] + M['-'][s2[j]];
for (int i = 1; i <= len1; i++){
for (int j = 1; j <= len2; j++){
dp[i][j] = max(dp[i - 1][j - 1] + M[s1[i]][s2[j]],
max(dp[i - 1][j] + M[s1[i]]['-'],
dp[i][j - 1] + M['-'][s2[j]]));
}
}
//输出
cout << dp[len1][len2] << endl;
}
return 0;
}
参考
Bellman算法,检查图中是否有正权回路。
正权回路:一个有向环,边的权重相加为正数。
POJ:Currency Exchange
O(m*n) time | O(n2) space
m——边数;n——点数。
参考文献:普林斯顿算法分析PPT