1、矩阵连乘积问题
void MatrixChain (int n)
{
for(int i=1; i<=n; i++)
m[i][i]=0;
for(int r=2; r<=n; r++)
{
for(int i=1; i<=n-r+1; i++)
{
int j=i+r-1;
m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(int k=i+1; k<j; k++)
{
int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
if(t<m[i][j])
{
m[i][j]=t;
s[i][j]=k;
}
}
}
}
}
//计算矩阵连乘积最优解的递归算法
void TraceBack(int i, int j)
{
if(i==j) cout<<i;
else
{
cout<<"(";
TraceBack(i,s[i][j]);
TraceBack(s[i][j]+1,j);
cout<<")";
}
}
//计算矩阵连乘积的备忘录算法
int LookupChain (int i, int j)
{
if(m[i][j]>0) return m[i][j];
if(i==j) return 0;
int u=LookupChain(i,i)+LookupChain(i+1,j)+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(int k=i+1; k<j; k++)
{
int t = LookupChain(i,k)+LookupChain(k+1,j)+p[i-1]*p[k]*p[j];
if(t<u)
{
u=t;
s[i][j]=k;
}
}
m[i][j]=u;
return u;
}
2、最长公共子序列
void LCSLength (int m, int n, const char x[],char y[])
{
int i,j;
for(i=1; i<=m; i++) c[i][0]=0;
for(j=1; j<=n; j++) c[0][j]=0;
for (i = 1; i <= m; i++)
for (j = 1; j <= n; j++)
{
if(x[i]==y[j])
{
c[i][j]=c[i-1][j-1]+1;
b[i][j]=1;
}
else if(c[i-1][j]>=c[i][j-1])
{
c[i][j]=c[i-1][j];
b[i][j]=2;
else
{
c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
}
}
//构造最长公共子序列
void LCS(int i,int j,char x[])
{
if(i==0||j==0) return ;
if(b[i][j]==1)
{
LCS(i-1,j-1,x);
cout<<x[i];
}
else if(b[i][j]==2)
LCS(i-1,j,x);
else
LCS(i,j-1,x);
}
3、最大子段和
//最优解
int MaxSum(int n,int &besti, int &bestj)
{
int sum=0;
int b=0;
int begin=0;
for(int i=0; i<n; i++)
{
if(b>0)
b+=a[i];
else
{
b=a[i];
begin=i;
}
if(b>sum)
{
sum=b;
besti = begin;
bestj = i;
}
}
return sum;
}
4、0-1背包问题(逆推)
void knapsack(int c, int n)
{
int jMax=min {w[n]-1,c}
for( int j=0; j<=jMax; j++) p[n][j]=0;
for( int j=w[n]; j<=c; j++) p[n][j]=v[n];
for( int i=n-1; i>1; i--)
{
jMax=min(w[i]-1,c);
for( int j=0; j<=jMax; j++)
p[i][j]=p[i+1][j];
for(int j=w[i]; j<=c; j++)
p[i][j]=max(p[i+1][j], p[i+1][j-w[i]]+v[i]);
}
p[1][c]=p[2][c];
if (c>=w[1]) p[1][c]=max(p[1][c], p[2][c-w[1]]+v[1]);
}
//最优解
void traceback( int c, int n, int x[ ])
{
for(int i=1; i<=n; i++)
{
if(p[i][c]==p[i+1][c])
x[i]=0;
else
{
x[i]=1;
c[i]-=w[i];
}
x[n]=(p[n][c])? 1:0;
}
}
5、最长单调递增子序列
int LIS_n2(int n)
{
int b[NUM]= {0}; //辅助数组
int i,j;
int max=0;
b[1]=1;
for (i=2; i<=n; i++)
{
int k=0;
for (j=1; j<i; j++) //0~i-1之间,b的最大值
if (a[j]<=a[i] && k<b[j])
k=b[j];
b[i] = k+1;
if (max<b[i]) max=b[i];
}
return max;
}
6、数字三角形问题
int triangle(int n)
{
int i, j;
for (i=n-2; i>=0; i--)
for (j=0; j<=i; j++)
if( tri[i+1][j] >tri[i+1][j+1])
tri[i][j] += tri[i+1][j];
else tri[i][j] += tri[i+1][j+1];
return tri[0][0];
}
7、FatMouse's Speed
//下面是针对排序后的数组
int count[1001] = {0}; //序列的最大长度
int path[1001] = {0}; //序列的前驱
count[1] = 1;
for(int i = 2; i < n; i++)
{
for(int j = 1; j<i; j++)
if(mice[i].weight>mice[j].weight && mice[i].speed<mice[j].speed)
if(count[i] < count[j]) //得到了更长的序列
{
count[i] = count[j];
path[i] = j; //记录前驱
}
count[i]++;
}
//查找最大的序列长度
int max = 0; //最大长度
int pos; //最大长度元素所在位置
for(int i = 1; i < n; i++)
if(count[i] > max)
{
max = count[i];
pos = i;
}
//输出最大长度
cout<<max;
//输出子序列序号的算法
void output(int path[], int pos)
{
if(pos == 0) return;
output(path, path[pos]);
cout<<mice[pos].id;
}
8、平分大理石块
void DP(int sum)
{
int i,j,k;
int mid = sum/2;
//大理石的状态数组
char visit[200];
memset(visit, 0, sizeof(visit));
int t;
visit[0] = 1;
//对每种价值的大理石块
for(i=1; i<=6; i++)
for(j=mid; j>=0; j- -)
//价值为j的分配方案存在
if (visit[j])
for(k=1; k<=a[i]; k++)
{
t = j+i*k;
if (t>mid) break;
//增加k块价值为i大理石,该平分方案仍然是成立的
else visit[t] = 1;
if (t==mid) { //找到了分配方案
printf("Can be divided.\n\n");
return;
}
}
cout<<"Can't be divided.";
}