Análise dinâmica de experimentos de programação

1. Soldados que não se atacam

Você tem um tabuleiro de xadrez unidimensional com n quadrados. Você pode colocar quantos soldados quiser no quadro. (Apenas um soldado pode ser colocado em cada grade). Um soldado atacará os soldados nas duas praças próximas a ele. Agora pergunte: quantos tipos de esquemas de colocação fazem os soldados no tabuleiro de xadrez não se atacarem?

Requisitos de tópico 1

Usamos 0 para nenhum soldado na grade e 1 para soldados na grade. Uma grade, dois estados 0, 1, duas grades 00, 01, 10, três grades 000, 001, 010, 100, 101, quatro grades 0000, 0001, 0010, 0100, 1000, 1001, 1010 Essa pergunta é muito simples, basta procurar as regras, mas porque você deseja escrever um relatório experimental ou seguir o processo experimental, certo
? Três grades 0 | 00, 0 | 01, 0 | 10, 10 | 0, 10 | 1
Quatro grades 0 | 000, 0 | 001, 0 | 010, 0 | 100, 0 | 101, 10 | 00, 10 | 01,10 | 10

  • Estado dividido (subproblema dividido): para esse problema, pode-se considerar que a solução ideal de n reticuladas consiste em 0 e n-1 reticuladas e 10 e n-2 reticuladas
  • Representação de estado: usamos f (n) para denotar a colocação de n grades
  • Equação de transferência de estado: f (n) = f (n-1) + f (n-2)
  • Determine o limite: o menor problema é 1 grade e 2 grades e não pode ser dividido; portanto, o valor do limite n = 1 en = 2

Agora que as equações de transição de estado e os valores limites foram determinados, a próxima solução direta é

#include<iostream>
using namespace std;
int f(int n){
	if(n==1) return 2;
  	else if(n==2) return 3;
  	else return f(n-1)+f(n-2);
}
int main(){
  	int n;
  	cin>>n;
  	cout<<f(n);
	return 0;
}

Acima, o código ecológico original: é claro, considerando os problemas de eficiência e otimização, usamos uma matriz unidimensional f [n] para simular o tabuleiro de xadrez, que será mais rápido e armazenará a solução ideal para cada estado.

#include<iostream>
using namespace std;
int f[50]={2,3};
int main(){
	for(int i=2;i<50;i++){
		f[i]=f[i-1]+f[i-2];
	}
  	int n;
  	cin>>n;
  	cout<<f[n-1];
	return 0;
}

O efeito é óbvio, antes da

otimização e após a otimização:

2. Subir escadas

Um dia, os dois começaram a partir do primeiro andar, para ver quem pode alcançar a mésima camada mais rapidamente, e A desce uma camada de cada vez, o que é obviamente muito lento.Por uma questão de justiça, B deu várias direções unidirecionais Fast track, você pode usar apenas 1s para ir da camada u para a camada v. Sabe-se que a camada adjacente precisa de 1s e pode ser movida para a próxima camada ou voltar para a camada anterior, podendo ser transferida apenas entre [1, m] camadas, ou seja, não pode atingir 0 ou m + 1 camadas. . Ajude A a calcular o tempo mínimo necessário para alcançar o mésimo andar e derrotar B (a pergunta original não é séria, um pouco mudou).

Essa pergunta é um pouco como o caminho mais curto de um gráfico, exceto que o peso de cada aresta é 1. A dica oficial diz para usar o algoritmo de Floyd, mas não me lembro de nada, apenas resolva-o com o bfs. Mas o experimento requer programação dinâmica, deixe-me escrever sobre isso. Veja o link abaixo para o algoritmo de Floyd.

Solução Floyd

Explicação detalhada do algoritmo de Floyd

  • Em suma, para o algoritmo de Floyd, primeiro estabeleça a matriz de adjacência dp [n] [n], para o algoritmo de Floyd, a equação de transição de estado é d [i] [j] = min {d [i] [j], d [i ] [k] + d [k] [j]}
    é o seguinte
#include<iostream>
#define INF 1000
using namespace std;

int dp[202][202]={0};

int main(){
    //初始化
  	int n,m;
  	cin>>n>>m;
  	for(int i=0;i<201;i++){
  	    for(int j=0;j<201;j++){
            if(i+1==j||i-1==j)
                dp[i][j]=1;
            else
                dp[i][j]=INF;
  	    }
  	}
  	int i,j;
  	while(n--){
        cin>>i>>j;
        dp[i][j]=1;
  	}
  	//算法
  	for(int k=1;k<=m;k++)
        for(int i=1;i<=m;i++)
            for(int j=1;j<=m;j++)
                if(dp[i][j]>dp[i][k]+dp[k][j])
                    dp[i][j]=dp[i][k]+dp[k][j];

    cout<<dp[1][m];
	return 0;
}

A complexidade do tempo de Floyd é O ( n 3 ) O (n ^ 3) , se você alternar para o primeiro bfs, a complexidade do tempo será O ( n ) O (n)

BFS (largura primeiro)

A idéia do algoritmo é inserir o primeiro vértice da equipe primeiro, atravessar todos os lugares onde o chefe da equipe pode alcançar e, em seguida, entrar na equipe e sair da equipe pela primeira vez. Continue a operação acima até que a fila esteja vazia (todos os vértices foram concluídos) Particularidade, todos os comprimentos de caminho são únicos.

O algoritmo é o seguinte

// 构建邻接矩阵
#include<iostream>
#define INF 1000
using namespace std;

int visit[202];
int a[202][202]={0};
void print(int m){
 for(int i=1;i<=m;i++){
        cout<<visit[i]<<" ";
    }cout<<endl;
}
int queue[1000];
int main(){
  	int n,m;
  	cin>>n>>m;
  	for(int i=0;i<201;i++){
        a[i][i+1]=a[i+1][i]=1;
        visit[i]=INF;
  	}
  	int i,j;
  	while(n--){
        cin>>i>>j;
        a[i][j]=1;
  	}

  	visit[1]=0;
  	int f=0,e=0;
    queue[e++]=1;
  	while(f<e){
        int x=queue[f];
        int y=visit[x];
        for(i=1;i<=m;i++){
            if(a[x][i]!=0){
                if(visit[i]>y+1){
                    visit[i]=y+1;
                    queue[e++]=i;
                }
            }
        }
        f++;
  	}
    cout<<visit[m];
	return 0;
}

Obviamente, mais rápido que Floyd.

Publicado 3 artigos originais · Gosto1 · Visitas 62

Acho que você gosta

Origin blog.csdn.net/weixin_43323747/article/details/105542230
Recomendado
Clasificación