一.最长公共子序列
1. 题面:
2. 题解:
如果s1的第i个字符和s2的第j个字符一样,dp[i][j]=dp[i-1][j-1]+1,如果不同,就等于max(dp[i-1][j],dp[i][j-1])
3. ac代码:
#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
//long long int dp2[400000],dp1[400000],a[400000];
using namespace std;
int main(){
char s1[200],s2[200];
int i,j;
int n1,n2;
int dp[200][200];
while(~scanf("%s%s",s1+1,s2+1)){
n1=strlen(s1+1);
n2=strlen(s2+1);
memset(dp,0,sizeof(dp));
for(i=1;i<=n1;i++){
for(j=1;j<=n2;j++){
if(s1[i]==s2[j]){
dp[i][j]=dp[i-1][j-1]+1;
}else{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
}
}
}
cout<<dp[n1][n2]<<endl;
}
}
二.最大子矩阵
1. 题面:
2. 题解:
看参考一
3. ac代码:
相较于参考1只是这部分有改动:
if(sum>0)
sum+=b[k];
else
sum=b[k];//可能矩阵全负
//sum=max(b[k],sum+b[k])
原来的:
sum+=b[k];
if(sum<0)
sum=b[k];//可能矩阵全负
不太懂原来的哪些情况会卡,求指教
#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
//long long int dp2[400000],dp1[400000],a[400000];
using namespace std;
typedef long long ll;
int main(){
int n;
int a[105][105];
int i,j,k;
int b[105];
while(cin>>n){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
cin>>a[i][j];
}
}
int maxn=-9999999;
for(i=1;i<=n;i++){
memset(b,0,sizeof(b));//每次开始行变化时都需要初始化b,b表示的是从i行到j行的最大子矩阵。
for(j=i;j<=n;j++){
int sum=0;
for(k=1;k<=n;k++){
b[k]+=a[j][k];
if(sum>0)
sum+=b[k];
else
sum=b[k];//可能矩阵全负
if(sum>maxn)
maxn=sum;
}
}
}
cout<<maxn<<endl;
}
}
//101010101000000111111
还有最常规的方法,是O(n^4)
详见该文
三.分苹果
1. 题面:
2. 题解:
1.递归:
设f(m,n) 为m个苹果,n个盘子的放法数目,则先对n作讨论,
当n>m:必定有n-m个盘子永远空着,去掉它们对摆放苹果方法数目不产生影响。即if(n>m) f(m,n) = f(m,m)
当n<=m:不同的放法可以分成两类:
1、有至少一个盘子空着,即相当于f(m,n) = f(m,n-1);
2、所有盘子都有苹果,相当于可以从每个盘子中拿掉一个苹果,不影响不同放法的数目,即f(m,n) = f(m-n,n).
而总的放苹果的放法数目等于两者的和,即 f(m,n) =f(m,n-1)+f(m-n,n)
递归出口条件说明:
当n=1时,所有苹果都必须放在一个盘子里,所以返回1;
当没有苹果可放时,定义为1种放法;
递归的两条路,第一条n会逐渐减少,终会到达出口n=1;
第二条m会逐渐减少,因为n>m时,我们会return f(m,m) 所以终会到达出口m=0.
2.dp:
新建一个动态规划表 dp;dp[i][j] 表示 i 个盘子放 j 个苹果的方法数。
则 当 i > j 时,dp[i][j] = dp[i - (i - j)][j] = dp[j][j]
当 i <= j 时,dp[i][j] = dp[i - 1][j] + dp[i][j - i];
最后dp[n][m] 就是所求。
3. ac代码:
#include<stdio.h>
#include<bits/stdc++.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
//long long int dp2[400000],dp1[400000],a[400000];
using namespace std;
typedef long long ll;
int dg(int n,int m){
if(n==0||m==1)
return 1;
if(n<m)
return dg(n,n);
return dg(n-m,m)+dg(n,m-1);
}
int main(){
int n,m,t,c;
while(cin>>t){
while(t--){
cin>>n>>m;
c=dg(n,m);
cout<<c<<endl;
}
}
}