• openjudge dp水题记录


    当发现自己竟然不会打dp的时候内心是崩溃的,然后按照一年前的刷题记录刷openjudge,然后发现自己准确率比一年前(刚学信竞两个月时)的准确率低得多,已经没救。

    列一下最近打的几道sb题

    2985:数字组合

    描述有n个正整数,找出其中和为t(t也是正整数)的可能的组合方式。如:

    n=5,5个数分别为1,2,3,4,5,t=5;

    那么可能的组合有5=1+4和5=2+3和5=5三种组合方式。输入输入的第一行是两个正整数n和t,用空格隔开,其中1<=n<=20,表示正整数的个数,t为要求的和(1<=t<=1000)

    接下来的一行是n个正整数,用空格隔开。输出和为t的不同的组合方式的数目。

    样例输入

    5 5 1 2 3 4 5

    样例输出

    3

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn=30;
    int n,t,tot,a[maxn],dp[maxn][1010];
    
    int aa;char cc;
    int read() {
    	aa=0;cc=getchar();
    	while(cc<'0'||cc>'9') cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa;
    }
    
    int main() {
    	n=read();t=read();
    	for(int i=1;i<=n;++i) {
    		a[i]=read();
    		if(a[i]>t) i--,n--;
    		else tot+=a[i];
    	}
    	if(tot<t) {
    		printf("0"); return 0;
    	}
    	dp[0][0]=1;
    	for(int i=1;i<=n;++i) {
    		for(int j=0;j<=t-a[i];++j) if(dp[i-1][j]) dp[i][j+a[i]]+=dp[i-1][j];
    		for(int j=0;j<=t;++j) dp[i][j]+=dp[i-1][j];
    	}
    	printf("%d",dp[n][t]);
    	return 0;
    }
    

      

    2988:计算字符串距离

    描述对于两个不同的字符串,我们有一套操作方法来把他们变得相同,具体方法为:

    1. 修改一个字符(如把“a”替换为“b”)

    2. 删除一个字符(如把“traveling”变为“travelng”)

    比如对于“abcdefg”和“abcdef”两个字符串来说,我们认为可以通过增加/减少一个“g”的方式来达到目的。无论增加还是减少“g”,我们都仅仅需要一次操作。我们把这个操作所需要的次数定义为两个字符串的距离。 
    给定任意两个字符串,写出一个算法来计算出他们的距离。输入第一行有一个整数n。表示测试数据的组数,
    接下来共n行,每行两个字符串,用空格隔开。表示要计算距离的两个字符串
    字符串长度不超过1000。输出针对每一组测试数据输出一个整数,值为两个字符串的距离。

    样例输入

    3 abcdefg abcdef ab ab mnklj jlknm

    样例输出

    1 0 4

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn=1000+10;
    int T,dp[maxn][maxn],lena,lenb;
    char a[maxn],b[maxn];
    
    int main() {
    	scanf("%d",&T);
    	while(T--) {
    		memset(dp,0x3f3f3f3f,sizeof(dp));
    		scanf("%s%s",a+1,b+1);  
    		lena=strlen(a+1); lenb=strlen(b+1);
    		for(int i=0;i<=lena||i<=lenb;++i) dp[0][i]=dp[i][0]=i;
    		for(int i=1;i<=lena;++i) for(int j=1;j<=lenb;++j) {
    			if(a[i]==b[j]) dp[i][j]=min(dp[i-1][j-1],dp[i][j]);//直接配对 
    			else dp[i][j]=min(dp[i-1][j-1]+1,dp[i][j]);//替换 
    			dp[i][j]=min(dp[i][j-1]+1,dp[i][j]);//插入
    			dp[i][j]=min(dp[i-1][j]+1,dp[i][j]);
    		}
    		printf("%d
    ",dp[lena][lenb]);
    	}
    	return 0;
    }
    

      

    3532:最大上升子序列和

    描述

    一个数的序列bi,当b1 < b2 < ... < bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1, a2, ...,aN),我们可以得到一些上升的子序列(ai1, ai2, ..., aiK),这里1 <= i1 < i2 < ... < iK <= N。比如,对于序列(1, 7, 3, 5, 9, 4, 8),有它的一些上升子序列,如(1, 7), (3, 4, 8)等等。这些子序列中序列和最大为18,为子序列(1, 3, 5, 9)的和.

    你的任务,就是对于给定的序列,求出最大上升子序列和。注意,最长的上升子序列的和不一定是最大的,比如序列(100, 1, 2, 3)的最大上升子序列和为100,而最长上升子序列为(1, 2, 3)

    输入输入的第一行是序列的长度N (1 <= N <= 1000)。第二行给出序列中的N个整数,这些整数的取值范围都在0到10000(可能重复)。输出最大上升子序列和

    样例输入

    7 1 7 3 5 9 4 8

    样例输出

    18

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn=1000+10,maxnum=1e4+10;
    int n,x,sz[maxnum],num[maxnum],ans,nowans;
    
    int aa;char cc;
    int read() {
    	aa=0;cc=getchar();
    	while(cc<'0'||cc>'9') cc=getchar();
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa;
    }
    
    int lb(int x) {
    	return x&(-x);
    }
    
    int rs;
    int q(int pos) {
    	rs=0;
    	while(pos) {
    		rs=max(rs,sz[pos]);
    		pos-=lb(pos);
    	}
    	return rs;
    }
    
    void chge(int pos,int x) {
    	while(pos<=1e4) {
    		sz[pos]=max(sz[pos],x);
    		pos+=lb(pos);
    	}
    }
    
    int main() {
    	n=read();
    	for(int i=1;i<=n;++i) {
    		x=read();
    		if(x) nowans=q(x-1)+x;
    		else nowans=0;
    		ans=max(ans,nowans);
    		if(nowans>num[x]) {
    			num[x]=nowans;
    			chge(x,nowans);
    		}
    	}
    	printf("%d",ans);
    	return 0;
    }
    

      

    8464:股票买卖

    描述

    最近越来越多的人都投身股市,阿福也有点心动了。谨记着“股市有风险,入市需谨慎”,阿福决定先来研究一下简化版的股票买卖问题。

    假设阿福已经准确预测出了某只股票在未来 N 天的价格,他希望买卖两次,使得获得的利润最高。为了计算简单起见,利润的计算方式为卖出的价格减去买入的价格。

    同一天可以进行多次买卖。但是在第一次买入之后,必须要先卖出,然后才可以第二次买入。

    现在,阿福想知道他最多可以获得多少利润。

    输入输入的第一行是一个整数 T (T <= 50) ,表示一共有 T 组数据。
    接下来的每组数据,第一行是一个整数 N (1 <= N <= 100, 000) ,表示一共有 N 天。第二行是 N 个被空格分开的整数,表示每天该股票的价格。该股票每天的价格的绝对值均不会超过 1,000,000 。输出对于每组数据,输出一行。该行包含一个整数,表示阿福能够获得的最大的利润。

    样例输入

    3 7 5 14 -2 4 9 3 17 6 6 8 7 4 1 -2 4 18 9 5 2

    样例输出

    28 2 0

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn=1e5+10,INF=1e7;
    int T,n,a[maxn],dd[maxn];
    
    int aa,ff;char cc;
    int read() {
    	aa=0;cc=getchar();ff=1;
    	while(cc<'0'||cc>'9') {
    		if(cc=='-') ff=-1;
    		cc=getchar();
    	}
    	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    	return aa*ff;
    }
    
    int main() {
    	T=read(); int num,ans,maxnum;
    	while(T--) {
    		n=read();ans=0;num=INF;maxnum=0;
    		for(int i=1;i<=n;++i) {
    			a[i]=read();
    			num=min(num,a[i]);
    			dd[i]=max(a[i]-num,dd[i-1]);
    		}
    		num=-INF;
    		for(int i=n;i;--i) {
    			num=max(num,a[i]);
    			maxnum=max(maxnum,num-a[i]);
    			ans=max(ans,dd[i]+maxnum);
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

      

    4982:踩方格

    描述

    有一个方格矩阵,矩阵边界在无穷远处。我们做如下假设:
    a.    每走一步时,只能从当前方格移动一格,走到某个相邻的方格上;
    b.    走过的格子立即塌陷无法再走第二次;
    c.    只能向北、东、西三个方向走;
    请问:如果允许在方格矩阵上走n步,共有多少种不同的方案。2种走法只要有一步不一样,即被认为是不同的方案。

    输入允许在方格上行走的步数n(n <= 20)输出计算出的方案数量

    样例输入

    2

    样例输出

    7

    //Serene
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxn=30;
    int n,dp[maxn][5];
    
    int main() {
    	scanf("%d",&n);
    	dp[1][0]=dp[1][1]=dp[1][2]=1;
    	for(int i=2;i<=n;++i) {
    		dp[i][0]=dp[i-1][0]+dp[i-1][1]+dp[i-1][2];
    		dp[i][1]=dp[i-1][0]+dp[i-1][1];
    		dp[i][2]=dp[i-1][0]+dp[i-1][2];
    	}
    	printf("%d",dp[n][0]+dp[n][1]+dp[n][2]);
    	return 0;
    }
    

      

    弱者就是会被欺负呀
  • 相关阅读:
    ssrf简介
    Mysql 命令 load data infile
    基于约束的SQL注入笔记
    ms17-010
    thinkphp5.0&5.1命令执行 和 thinkphp3.2.3sql注入
    抓取分析菜刀流量
    lamp环境的搭建
    php伪协议
    LeetCode-336 Palindrome Pairs
    LeetCode-335 Self Crossing
  • 原文地址:https://www.cnblogs.com/Serene-shixinyi/p/7474988.html
Copyright © 2020-2023  润新知