最长不下降子序列
不用我说了吧
有一个O(nlogn)的做法
最长公共子序列
#include<stdio.h>
using namespace std;
char a[30001],b[30001];
int dp[3001][3001];
int main()
{
scanf("%s",a+1);scanf("%s",b+1);
for(int i=1;i<=strlen(a+1);i++)
for(int j=1;j<=strlen(b+1);j++)
{
int pc;
pc=dp[i-1][j-1]+(a[i]==b[j]);
dp[i][j]=max(pc,max(dp[i-1][j],dp[i][j-1]));
}
printf("%d",dp[strlen(a+1)][strlen(b+1)]);
}
水!
错位排序
#include<stdio.h>
int main()
{
int i,n,T;
double a[21]={0,0,1};
double b[21]={1,1,2};//定义为double型就不需使用long long,同时输出不需要转换类型
for(i=3;i<=20;++i)
{
a[i]=(a[i-1]+a[i-2])*(i-1); //错排公式--不懂的可以参考信封装错的那题
b[i]=b[i-1]*i;
}
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("%.2lf%%\n",a[n]/b[n]*100);
}
return 0;
}
不知道自己为什么会错,和正解输出一样qwq
用 1 × 2 的覆盖 2 × n 的矩形
我不会告诉你他是斐波那契数列..
最后一步时,可以竖着放一个1*2的,也可以横着放两个1*2的,这样
f[i]=f[i-1]+f[i-2]
本题实质为正整数无序分拆,那么设f[i,j]表示数i拆分为j部分的方案数,如果拆分出来的数有1,那么1单独分成一部分,那么有f[i,j-1],无1,那么将已拆分的每一个数减1:f[i-j,j]。
综上有:f[i,j]=f[i,j-1]+f[i-j,j],边界:f[0,0]=0。 结果ans=∑f[n,i](2<=i<=n)
//代码里的i,j好像和题解里反了。。qwq
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
unsigned int n,dp[4005][4005],ans,mod = 2147483648;
int main(){
cin>>n;
dp[0][0] = 1;
for(int i = 1;i <= n;i++){
for(int j = i;j <= n;j++){
dp[i][j] = (dp[i-1][j-1] + dp[i][j-i]) % mod;
if(i > 1 && j == n) ans = (ans + dp[i][j]) % mod;
}
}
cout<<ans;
return 0;
}
单调栈
有个东西叫单调栈
跟单调队列不同的是单调队列还有长度的限制,单调栈没有 Largest Rectangle in a
Histogram其实就是一个单调栈,每次把一个矩形最左能到达的地方和最右能到达的地方找出来
最后max ans
#include<iostream>
#include<cstdio>
using namespace std;
long long n,a[100001],b[1000001]/*开始位置*/,c[1000001]/*结束位置*/,
d[1000001],stack[1000001]/*单调栈*/,tail,ans;
int main()
{
// freopen("1.txt","r",stdin);
while(scanf("%lld",&n)&&n!=0)
{
for(int i=1;i<=n;i++)
{
b[i]=c[i]=d[i]=0;
}
ans=0;tail=1;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
stack[1]=a[1];
b[1]=1;d[1]=1;
for(int i=2;i<=n;i++)
{
if(a[i]>=stack[tail])
{
tail++;
stack[tail]=a[i];
d[tail]=i;
b[i]=i;
}
else
{
while(a[i]<stack[tail]&&tail)
{
c[d[tail]]=i-1;
tail--;
}
b[i]=b[d[++tail]];
d[tail]=i;
stack[tail]=a[i];
}
}
for(int i=1;i<=n;i++)
{
if(c[i]==0)
{
ans=max(ans,a[i]*(n-b[i]+1));
}
else ans=max(ans,a[i]*(c[i]-b[i]+1));
}
printf("%lld\n",ans);
}
}
单调队列
Sliding Window
我没有做对,不知道为什么wa。。。
单调队列模板题
#include<iostream>
#include<cstdio>
using namespace std;
int n,a[5000001],head,tail=1,stack[5000001],pos[5000001],k;
int main()
{
// freopen("1.txt","r",stdin);
cin>>n>>k;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
pos[1]=1;
stack[1]=a[1];
head=1;
for(int i=2;i<=n;i++)
{
if(pos[head]+k==i) head++;
if(a[i]>=stack[tail])
{
tail++;
stack[tail]=a[i];
pos[tail]=i;
}
else
{
do
{
tail--;
}
while(a[i]<stack[tail]&&tail>=head);
stack[++tail]=a[i];
pos[tail]=i;
}
if(i>=k)
printf("%d ",stack[head]);
}
printf("\n");
for(int i=1;i<=n;i++)
{
stack[i]=pos[i]=0;
}
head=0;tail=1;
stack[++head]=a[1];
pos[1]=1;
for(int i=2;i<=n;i++)
{
if(pos[head]+k==i) head++;
if(a[i]<=stack[tail])
{
stack[++tail]=a[i];
pos[tail]=i;
}
else
{
do
{
tail--;
}
while(a[i]>stack[tail]&&tail>=head);
stack[++tail]=a[i];
pos[tail]=i;
}
if(i>=k) printf("%d ",stack[head]);
}
}
我的代码非常好,只是它过不了。。
最大正方形
给你一个01矩阵,求最大的全是1的正方形
//偷别人的代码
#include <stdio.h>
#define MAX 500
int matrix[MAX][MAX];
int min(int a, int b){
return a < b ? a : b;
}
int main()
{
int max = 1;
int m, n;
scanf("%d%d", &m,&n);
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
scanf("%d", &matrix[i][j]);
for(int i = 1; i < m; i++)
for(int j = 1; j < n; j++)
if(matrix[i][j] == 1)
{
int mmin = min(matrix[i - 1][j], matrix[i][j - 1]);
mmin = min(matrix[i - 1][j - 1], mmin);
matrix[i][j] = mmin + 1;
if(max < matrix[i][j])
max = matrix[i][j];
}
printf("%d", max);
return 0;
}
设matrix[i][j]表示以(i,j)为右下角的最大正方形边长
初始值1的矩阵matrix值为1
更新时matrix=min(matrix[i - 1][j], matrix[i][j - 1],matrix[i - 1][j - 1])
可以自己画图试一下,很好证明
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t,a[100001],n,sum,f,l,ff,ll,b;
int main()
{
// freopen("1.txt","r",stdin);
// freopen("2.txt","w",stdout);
cin>>t;
for(int o=1;o<=t;o++)
{
memset(a,0,sizeof(a));
f=l=1;ff=ll=1;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sum=a[1];b=a[1];
for(int i=2;i<=n;i++)
{
if(b<0)
{
b=a[i];
ff=ll=i;
}
else
{
b=b+a[i];
ll=i;
}
if(b>sum)
{
sum=b;
f=ff;
l=ll;
}
}
printf("Case %d:\n",o);
printf("%d %d %d\n",sum,f,l);
if(o!=t) printf("\n");
}
}
poj1050最大子矩阵
和上题一样
//http://poj.org/problem?id=1050
//很水和hdu1003一样
#include<iostream>
#include<cstdio>
using namespace std;
int n,k,a[101][101],maxn,b;
int main()
{
// freopen("1.txt","r",stdin);
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
a[i][j]+=a[i-1][j];
}
maxn=a[1][1];
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j++)
{
b=0;
for(int k=1;k<=n;k++)
{
if(b<0) b=a[j][k]-a[i-1][k];
else b+=a[j][k]-a[i-1][k];
maxn=max(b,maxn);
}
}
printf("%d",maxn);
}
\ /
-->*<--
/o\
/_\_\
/_/_0_\
/_o_\_\_\
/_/_/_/_/o\
/@\_\_\@\_\_\
/_/_/O/_/_/_/_\
/_\_\_\_\_\o\_\_\
/_/0/_/_/_0_/_/@/_\
/_\_\_\_\_\_\_\_\_\_\
/_/o/_/_/@/_/_/o/_/0/_\
[___]
。。。