最长公共子序列
【问题描述】给定两个字符串text1和text2,返回这两个字符串的最长公共子序列的长度。如果不存在公共子序列,则返回0。一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。
【输入形式】输入的第1行中有一个字符串,表示text1;输入的第2行中有一个字符串,表示text2。
【输出形式】输出1行一个整数,表示text1和text2的最长公共子序列的长度。
【样例输入】
abcde
ace
【样例输出】
3
【样例说明】
最长公共子序列是ace,长度为3
【说明】
1<=text1.length, text2.length<=1000
text1和text2仅有小写英文字符组成。
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
string text1,text2;
int dp[N][N];
int main()
{
cin>>text1>>text2;
// cout << text1.length()<<endl;
for(int i=0;i<=text1.length();i++)
{
dp[i][0]=0;
}
for(int i=0;i<=text2.length();i++)
{
dp[0][i]=0;
}
for(int i=1;i<=text1.length();i++)
{
for(int j=1;j<=text2.length();j++)
{
if(text1[i-1]==text2[j-1])
{
dp[i][j]=dp[i-1][j-1]+1;
}
else
{
dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
}
//cout << dp[i][j]<<endl;
}
}
cout<<dp[text1.length()][text2.length()];
return 0;
}
矩阵链相乘
【问题描述】给定n个矩阵M1,M2...Mn,他们的维数分别是r1*c1,r2*c2...rn*cn,要求使用【动态规划】的策略求解矩阵连乘的最优计算代价(总乘法次数最少)。题目保证矩阵相乘一定是有效的。
例如有三个矩阵M1,M2,M3,他们的维度分别是2*10,10*2,2*10。按照矩阵乘法的结合律,可以先把M1和M2相乘,然后把结果和M3相乘,总的乘法次数为2*10*2+2*2*10=80次;也可以先把M2和M3相乘,再用M1去相乘,这种方式下总的乘法次数为10*2*10+2*10*10=400次。因此最优计算代价为80。
【输入形式】输入的第1行中有1个数字n,表示矩阵的个数;接下来n行,每行2个整数ri和ci,分别表示矩阵Mi的行数和列数。
【输出形式】输出1行中有一个数字,表示n个矩阵相乘的最优计算代价。
【样例输入】
3
2 10
10 2
2 10
【样例输出】
80
【说明】
n>=2
1<=ri,ci<=20
#include<bits/stdc++.h>
using namespace std;
const int N=30,Inf=1e8+20;
int n;
int m[N][N],a[3*N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
m[i][i]=0;
}
cin>>a[0];
int num=1;
for(int i=1;i<2*n;i++)
{
int t;
cin>>t;
if(i%2==1)
{
a[num++]=t;
}
}
for(int d=2;d<=n;d++)
{
for(int i=1;i<=n-d+1;i++)
{
int j=i+d-1;
m[i][j]=Inf;
for(int k=i;k<j;k++)
{
int temp=m[i][k]+m[k+1][j]+a[i-1]*a[k]*a[j];
if(temp<m[i][j])
{
m[i][j]=temp;
}
//cout << m[i][j]<<" "<<i<<" "<<j<<endl;
}
}
}
cout << m[1][n];
return 0;
}
所有点对的最短路径问题
【问题描述】给定一个非负的加权有向图G,求其中任意两个节点之间的最短路径。
【输入形式】输入的第1行包含2个整数n和m,表示图G中包含n个节点和m条边。接下来m行,每行中有3个整数i,j,w,表示从节点i到节点j存在一条边(节点编号从1开始),该边的权重为w。
【输出形式】
输出最短路径矩阵,共包含n行,每行包含n个数字(数字之间使用空格分割),表示该节点到其他节点的最短距离。
特别地,节点到自身的距离定义为0;如果节点之间无法到达,使用1e9+7表示他们之间的距离。
【样例输入】
3 5
1 2 2
1 3 9
2 1 8
2 3 6
3 1 1
【样例输出】
0 2 8
7 0 6
1 3 0
【思考】如果出现负边,如何进行改进
#include<bits/stdc++.h>
using namespace std;
const int N=1010,inf=1e9+7;
int n,m;
int g[N][N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) g[i][j]=0;
else
g[i][j]=inf;
}
}
for(int k=1;k<=m;k++)
{
int i,j,w;
cin>>i>>j>>w;
g[i][j]=w;
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
{
continue;
}
if(g[i][k]+g[k][j]<g[i][j])
{
g[i][j]=g[i][k]+g[k][j];
}
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cout << g[i][j]<<" ";
}
cout << endl;
}
}
01背包问题
【问题描述】给定一个容量为C的背包,现有n个物品,每个物品的体积分别为s1,s2...sn,价值分别为v1,v2...vn。每个物品只能放入一次。背包最多能装入价值为多少的物品。
【输入形式】输入的第1行包含2个整数C和n,分别表示背包容量和物品个数。接下来n行,每行包含2个整数si和vi,分别表示物品的体积和价值。
【输出形式】输出1行中含有一个数字,表示背包能装入的物品的最大价值。
【样例输入】
9 4
2 3
3 4
4 5
5 7
【样例输出】
12
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int c,n,dp[N][N];
int s[N],v[N];
int main()
{
cin>>c>>n;
for(int i=1;i<=n;i++)
{
cin>>s[i]>>v[i];
//tiji >> jiazhi
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=c;j++)
{
if(j<s[i])
dp[i][j]=dp[i-1][j];
else
dp[i][j]=max(dp[i-1][j],dp[i-1][j-s[i]]+v[i]);
}
}
cout <<dp[n][c];
return 0;
}
最少费用购物----动态规划
问题描述:
商店中每种商品都有标价。例如,一朵花的价格是2 元。一个花瓶的价格是5 元。为了吸引顾客,商店提供了一组优惠商品价。优惠商品是把一种或多种商品分成一组,并降价销售。例如,3 朵花的价格不是6 元而是5 元。2 个花瓶加1 朵花的优惠价是10 元。试设计一个算法,计算出某一顾客所购商品应付的最少费用。
编程任务:
对于给定欲购商品的价格和数量,以及优惠商品价,编程计算所购商品应付的最少费用。
数据输入:
由文件input.txt 提供欲购商品数据。文件的第1 行中有1 个整数B(0≤B≤5),表示所购商品种类数。接下来的B 行,每行有3 个数C,K 和P。C 表示商品的编码(每种商品有唯一编码),1≤C≤999。K 表示购买该种商品总数,1≤K≤5。P 是该种商品的正常单价(每件商品的价格),1≤P≤999。请注意,一次最多可购买5*5=25 件商品。
由文件offer.txt 提供优惠商品价数据。文件的第1 行中有1 个整数S(0≤S≤99),表示共有S 种优惠商品组合。接下来的S 行,每行的第一个数描述优惠商品组合中商品的种类数j。接着是j 个数字对(C,K),其中C 是商品编码,1≤C≤999。K 表示该种商品在此组合中的数量,1≤K≤5。每行最后一个数字P(1≤ P≤9999 )表示此商品组合的优惠价。
结果输出:
程序运行结束时,将计算出的所购商品应付的最少费用输出到文件output.txt 中。
输入文件示例 输出文件示例
input.txt offer.txt output.txt
2 2 14
7 3 2 1 7 3 5
8 2 5 2 7 1 8 2 10
/*
2
7 3 2
8 2 5
2
1 7 3 5
2 7 1 8 2 10
*/
#include<bits/stdc++.h>
using namespace std;
const int N=1010;
int b,s;
struct pd
{
int c,k,p;
}p[N];
int pos[N];//用于记录商品编码的位置
int zuhe[100][6]={0};
//zuhe[i][j]: 商品组合的优惠价(j=0);某种优惠组合中某种商品需要购买的数量(j>0)
int num[6]={0};//用于记录每个商品要买多少个
int cost[6][6][6][6][6];
void mini()
{
int i,j,k,m,n;
int t;
int sum1=0;
for(i=1;i<=b;i++)
sum1+=num[i]*p[i].p;
for(t=1;t<=s;t++)
{
i=num[1]-zuhe[t][1];
j=num[2]-zuhe[t][2];
k=num[3]-zuhe[t][3];
m=num[4]-zuhe[t][4];
n=num[5]-zuhe[t][5];
if(i<0 || j<0 || k<0 || m<0 || n<0) continue;
if(cost[i][j][k][m][n]+zuhe[t][0]<sum1)
{
sum1=cost[i][j][k][m][n]+zuhe[t][0];
}
}
cost[num[1]][num[2]][num[3]][num[4]][num[5]]=sum1;
}
void dfs(int x)
{
if(x>b)
{
mini();
return ;
}
for(int j=0;j<=p[x].k;j++)
{
num[x]=j;
dfs(x+1);
}
}
int main()
{
cin>>b;
for(int i=1;i<=b;i++)
{
cin>>p[i].c>>p[i].k>>p[i].p;
pos[p[i].c]=i;
}
cin>>s;
for(int i=1;i<=s;i++)
{
int t;
cin>>t;
for(int j=1;j<=t;j++)
{
int cc,kk;
cin>>cc>>kk;
zuhe[i][pos[cc]]=kk;
}
cin>>zuhe[i][0];
}
dfs(1);
cout << cost[num[1]][num[2]][num[3]][num[4]][num[5]];
}