Algoritmo esencial de Blue Bridge Cup 3: Programación dinámica

Principio del algoritmo

1.0 Introducción al algoritmo

Creo que todos saben que el algoritmo de programación dinámica también es un problema que preocupa mucho a los novatos cuando son nuevos en el diseño de algoritmos. A veces les resulta difícil de entender, pero después de que realmente lo entienden, sentirán que la programación dinámica es realmente no es tan difícil como imaginaba. También hay muchos artículos en Internet sobre cómo explicar la programación dinámica. La mayoría de ellos describen conceptos y explican principios, lo que hace que las personas se sientan oscuras y difíciles de entender. Creo que lo más importante para entender el algoritmo es la práctica, solo practicando solo puedes mejorar más rápido. Un problema de optimización resuelto por un método de programación dinámica debe tener dos elementos: subestructura óptima y superposición de subproblemas. También discutiremos el método de memorización nuevamente, discutiendo con más profundidad cómo se puede usar el mecanismo de memorización para aprovechar el subproblema superpuesto en el método de arriba hacia abajo.

2.0 ¿Qué problemas se pueden resolver mediante programación dinámica?

Los problemas que pueden resolverse mediante programación dinámica generalmente tienen tres propiedades:

  1. Principio de optimización: Si la solución de los subproblemas contenidos en la solución óptima del problema también es óptima, se dice que el problema tiene una subestructura óptima, es decir, se cumple el principio de optimización.
  2. Sin repercusión: es decir, una vez determinado el estado de una determinada etapa, no se verá afectado por decisiones posteriores de dicho estado. Es decir, el proceso posterior a un determinado estado no afectará al estado anterior, solo relacionado con el estado actual.
  3. Hay subproblemas superpuestos: es decir, los subproblemas no son independientes y un subproblema se puede utilizar varias veces en la siguiente etapa de toma de decisiones. (Esta propiedad no es una condición necesaria para la aplicación de la programación dinámica, pero sin esta propiedad, el algoritmo de programación dinámica no tiene ventaja sobre otros algoritmos)

3.0 Pasos para resolver problemas

Generalmente resolvemos problemas de programación dinámica en cuatro pasos:

  1. Definir un estado, que es la característica estructural de una solución óptima.
  2. Realizar recursividad de estado para obtener la fórmula recursiva
  3. inicializar
  4. resultado devuelto

ejemplo clásico

Águila come pollito

Tema Descripción

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

Ideas y códigos de temas

Idea: problema de la mochila

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const ll maxn=1e5+10;
ll n;
ll a[maxn],b[maxn];
ll dp[100010];
ll sum=0;
int main(){
    
    
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
    
    
        scanf("%lld",&b[i]);
    }
    for(int i=1;i<=n;i++){
    
    
        scanf("%lld",&a[i]);
    }
    ll ma=0;
    for(int i=1;i<=n;i++){
    
    
        for(ll j=n;j>=b[i];j--){
    
    
            dp[j]=max(dp[j],dp[j-b[i]]+a[i]);
            ma=max(ma,dp[j]);

        }

    }
    printf("%lld",ma);
	return 0;
}


quitar corchetes

Enlace: enlace del título original
Fuente: Niuke.com

Tema Descripción

给你一个合法的括号序列s1,每次你可以删除一个"()"
你可以删除0个或者多个"()"
求能否删成另一个括号序列s2

输入描述:
第一行输入一个字符串s (2|s|100)
第二行输入一个字符串t (2|t|100 )
输出描述:
如果可以输出"Possible"
否则输出"Impossible"

¡Abra el enlace del tema para entrada y salida!

Ideas y códigos de temas

Idea: Use k= para borrar el número de '('-delete')', vea el código para más detalles
Código:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll N=105;
bool dp[N][N][N];
char str[N],str1[N];
int main()
{
    
    
 ios::sync_with_stdio(false);
 cin.tie(0);
 cout.tie(0);//对cin,cout的优化 
 cin>>str+1;
 cin>>str1+1;
 dp[0][0][0]=true;//边界初始化 
 for(int i=0;i<=strlen(str+1) ;i++)
 {
    
    
  for(int j=0;j<=strlen(str1+1) ;j++)
  {
    
    
   for(int k=0;k<=strlen(str+1)/2;k++)
   {
    
    
    if(dp[i][j][k])
    {
    
    
     if(!k&&str[i+1]==str1[j+1])dp[i+1][j+1][k]=true;//如果成立则前i+1中和j+1相匹配 
     if(str[i+1]=='(')dp[i+1][j][k+1]=true;//无论成立不,都要试试删除str[i+1] 
     else if(k)dp[i+1][j][k-1]=true; //如果有')',则有一对被删,k--; 
    }
   }
  }
 }
 if(dp[strlen(str+1)][strlen(str1+1)][0])cout<<"Possible"<<endl;//遍历到最后看看是否有成立的情况 
 else cout<<"Impossible"<<endl;
 return 0;
 }

Para otros temas, lea la columna de programación dinámica. ! !

Epílogo


"Si estás indeciso, puedes preguntarle a la brisa primaveral, y si la brisa primaveral no habla, seguirás a tu corazón" significa: si tienes dudas sobre algo, pregúntale a la brisa primaveral cómo hacerlo. . "Si no está decidido, puede preguntarle a la brisa primaveral. Si la brisa primaveral no habla, seguirá su corazón". La oración proviene del "Jianlai" escrito por el escritor de Internet "Fenghuo Opera Princes". El texto original es: "Si estás indeciso, puedes preguntarle a la brisa primaveral. Sigue tu corazón".

inserte la descripción de la imagen aquí


Supongo que te gusta

Origin blog.csdn.net/weixin_46627433/article/details/123647844
Recomendado
Clasificación