2021-01-11DP(補完)

1.最長共通部分列

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;
	}


}

2.最大の部分行列


参考文献1
(完全に正しくない)
参考文献2

1.トピック:

ここに画像の説明を挿入

2.解決策:解決策:

参考文献1を参照

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の場合:常に空のnm個のプレートが必要です。それらを削除しても、リンゴの数には影響しません。インパクト。つまり、if(n> m)f(m、n)= f(m、m)  
when n <= m:異なる配置方法は2つのカテゴリに分類できます:
1。少なくとも1つのプレートが空であり、これは次のようになります。 f(m、n)= f(m、n-1);
2.すべてのプレートにリンゴがあります。これは、異なる配置方法の数に影響を与えることなく、各プレートから1つのリンゴを取り除くことに相当します。つまり、f(m 、n)= f(mn、n)。
そして、リンゴを置く方法の総数は、2つの合計に等しくなりますつまり、f(m、n)= f(m、n-1)+ f( mn、n)
再帰的終了条件の説明:
n = 1の場合、すべてのリンゴをプレートに配置する必要があるため、1を返します。配置する
リンゴがない場合は、配置の1つの方法として定義されます
。2つの再帰的パス、最初のnは徐々に減少し、最終的に出口n = 1に到達します
。2番目のmは徐々に減少します。これは、n> mの場合、f(m、m)を返すため、最終的に出口m = 0に到達するためです。

2.dp:
新しい動的計画法テーブルdpを作成します。dp [i] [j]は、j個のリンゴをiプレートに配置する方法の数を表します。
次に、i> jの場合、dp [i] [j] = dp [i-(i-j)] [j] = dp [j] [j]
i <= jの場合、dp [i] [j] = dp [i -1] [j] + dp [i] [ji];
最後に、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;
		}
	}
	
}

おすすめ

転載: blog.csdn.net/weixin_46064382/article/details/112549131