P1006 [Grupo de Melhorias NOIP2008] Passe a nota
descrição do tópico
Xiaoyuan e Xiaoxuan são bons amigos e colegas de classe e sempre têm assuntos intermináveis para conversar juntos. Em uma atividade de desenvolvimento de qualidade, os alunos da turma se sentaram em um mmm linhannUma matriz com n colunas, e Xiaoyuan e Xiaoxuan estão dispostos em ambas as extremidades da diagonal da matriz, de modo que não podem se comunicar diretamente. Felizmente, eles podem se comunicar passando bilhetes. A nota será passada entre si por muitos colegas. Xiaoyuan fica no canto superior esquerdo da matriz e as coordenadas são(1,1) (1,1)( 1 ,1 ) , Xiaoxuan fica no canto inferior direito da matriz, coordenadas( m , n ) (m,n)( m ,n ) . A nota passada de Xiaoyuan para Xiaoxuan só pode ser passada para baixo ou para a direita, e a nota passada de Xiaoxuan para Xiaoyuan só pode ser passada para cima ou para a esquerda.
Durante a atividade, Xiaoyuan espera passar um bilhete para Xiaoxuan e, ao mesmo tempo, espera que Xiaoxuan responda a ele. Todos os alunos da classe podem repassar para eles, mas apenas uma vez, ou seja, se essa pessoa ajudar quando Xiaoyuan passar o bilhete para Xiaoxuan, então ele não ajudará quando Xiaoxuan passar para Xiaoyuan. Ajude novamente. vice-versa.
Há mais uma coisa para prestar atenção. A favorabilidade de cada aluno da classe é alta ou baixa (Nota: a bondade de Xiaoyuan e Xiaoxuan não está definida, use 0 0 ao entrar0 ), você pode usar[ 0 , 100 ] [0,100][ 0 ,100 ] para representar um número natural, quanto maior o número, melhor a intenção. Xiaoyuan e Xiaoxuan esperam encontrar alunos com altos níveis de bondade para ajudar a passar a nota o máximo possível, ou seja, encontrar dois caminhos de transmissão de ida e volta, para que a soma da gentileza dos alunos nesses dois caminhos seja o maior. Agora, por favor, ajude Xiaoyuan e Xiaoxuan a encontrar esses dois caminhos.
Formato de entrada
A primeira linha tem dois inteiros mm separados por espaçosm ennn , significa que hámmm linhannn colunas.
próximo mmm linhas são am × nm \times nm×A matriz de n , o iithna matrizeu remojjO número inteiro na coluna j significa estar noiieu remojjA bondade do aluno na coluna j . nnpara cada linhaOs n inteiros são separados por espaços.
Formato de saída
O arquivo de saída é composto por um inteiro por linha, que representa o valor máximo da soma das gentilezas dos alunos que participaram da passagem das notas nas duas idas e vindas.
Exemplo 1
Exemplo de Entrada #1
3 3
0 3 9
2 8 5
5 7 0
Saída de amostra nº 1
34
dica
【intervalo de dados】
Por 30% 30\%30% dos dados satisfazem1 ≤ m , n ≤ 10 1 \le m,n \le 101≤m ,n≤10 .
Para100% 100\%100% dos dados, satisfazendo1 ≤ m , n ≤ 50 1 \le m,n \le 501≤m ,n≤50。
[fonte do tópico]
A terceira pergunta do grupo de aprimoramento do NOIP 2008.
linha de raciocínio
dp quadridimensional
Este problema é encontrar as duas maiores linhas que não se sobrepõem. Embora se diga que um começa no canto superior esquerdo e o outro no canto inferior direito, na verdade ambos começam no canto superior esquerdo, que é mais fácil de pensar e mais fácil de escrever
. , dp ! ! ! A melhor coisa a se pensar é o dp quadridimensional :
dp [ i ] [ j ] [ u ] [ v ] dp[i][j][u][v]d p [ i ] [ j ] [ u ] [ v ] significa que a primeira linha atingiu( i , j ) (i, j)(eu ,j ) , a segunda linha atinge( u , v ) (u,v)( você ,v )
Claro, duas linhas não podem ir para o mesmo ponto, então no loopi, j, u, vi,j,u,veu ,j ,você ,quando v ,vvv é começar dej + 1 j+1j+1 ,
ou julgar quando dois pontos coincidem,dp [i] [j] [u] [v] dp[i][j][u][v]d p [ i ] [ j ] [ u ] [ v ] menos a bondade de uma pessoa
É melhor pensar na equação de transição de estado quadridimensional:
f[i][j][k][l]=max( f[i][j-1][k-1][l] , max(f[i-1][j][k][l-1] , max(f[i][j-1][k][l-1] , f[i-1][j][k-1][l]) ) )+a[i][j]+a[k][l]
a é a bondade da entrada! ! !
Que tal isso? muito simples né?
No entanto, quando os dados são maiores, o quadridimensional não pode ser usado. Este 1 ≤ m , n ≤ 50 1≤m, n≤501≤m ,n≤50 é realmente um pouco aguado, então precisamos usar tridimensional,é claro que tridimensional também é fácil de entender.
dp tridimensional
Podemos descobrir que o número total de passos percorridos pelas duas rotas é o mesmo (ou seja, i + j i+jeu+j igual au + v u + vvocê+v ),portanto, podemos apenas enumerar as coordenadas verticais ou horizontais das duas linhas. (enumero as abcissas)
Então nosso atual dp [k] [i] [j] dp[k][i][j]d p [ k ] [ i ] [ j ] significa queum total de k passos foram dados, a primeira linha está na i-ésima coluna e a segunda linha está na j-ésima coluna. Atenção
! ! ! A primeira dimensão da matriz dp deve ser aberta para n + m n+mn+Mais do que m , porque esta matriz de xadrez pode ir até cerca den + m n+mn+m etapas
Então nossa equação de transição de estado é:
dp[k][i][j]=max_(dp[k-1][i-1][j-1],dp[k-1][i][j],dp[k-1][i-1][j],dp[k-1][i][j-1])+a[i][k-i]+a[j][k-j];
max_ é uma função que encontra o valor máximo de quatro números, mas você também pode escrever três valores máximos
:
dp [ k − 1 ] [ i − 1 ] [ j − 1 ] dp[k-1][i-1 ][ j-1]d p [ k−1 ] [ eu−1 ] [ j−1 ] significa: ambas as linhas se movem para baixo na etapa anterior;
dp [ k − 1 ] [ i ] [ j ] dp[k-1][i][j]d p [ k−1 ] [ i ] [ j ] significa: ambas as linhas se movem para a direita no passo anterior;
dp [ k − 1 ] [ i − 1 ] [ j ] dp[k-1][i-1][j]d p [ k−1 ] [ eu−1 ] [ j ] significa: no último degrau, um desce e o outro vai para a direita;
dp [ k − 1 ] [ i ] [ j − 1 ] dp[k-1][i][j-1]d p [ k−1 ] [ i ] [ j−1 ] significa: no último degrau, um está à direita e o outro deve descer;
aaA matriz é a bondade da entrada
É isso, bem simples, não é? Dê uma olhada no código:
Contém notas, coma com confiança:
Código quadridimensional CA:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 55
using namespace std;
int a[N][N],f[N][N][N][N];
void work(int i,int j,int k,int l)
{
int Max=0;
Max=max(Max,f[i-1][j][k-1][l]);//这里可以合并,看个人喜好
Max=max(Max,f[i-1][j][k][l-1]);
Max=max(Max,f[i][j-1][k-1][l]);
Max=max(Max,f[i][j-1][k][l-1]);
f[i][j][k][l]=Max+a[i][j];
if(i!=k||j!=l)//去重,因为题目不允许走到同一个点
f[i][j][k][l]+=a[k][l];
}
int main()
{
int m,n,i,j,k,l;
scanf("%d%d",&m,&n);
for(i=1;i<=m;++i)
for(j=1;j<=n;++j)
scanf("%d",&a[i][j]);
for(i=1;i<=m;++i)
for(j=1;j<=n;++j)
for(u=1;u<=m;++u)
for(v=1;v<=n;++v)
work(i,j,u,v);
printf("%d",f[m][n][m][n]);
return 0;
}
Código CA 3D:
#include<bits/stdc++.h>
using namespace std;
int n,m,a[101][101],dp[201][101][101];
int max_(int a,int b,int c,int d){
return max(a,max(b,max(c,d)));//求最大的
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
for(int k=2;k<=n+m;k++){
//枚举步数
for(int i=1;i<=n;i++){
//枚举横坐标
for(int j=1;j<=n;j++){
//枚举横坐标
int l1=k-i,l2=k-j;
if(l1<1||l1>m||l2<1||l2>m) continue;
int t=a[i][l1];
if(i!=j) t+=a[j][l2];//如果没有重复就加上
dp[k][i][j]=max_(dp[k-1][i-1][j-1],dp[k-1][i][j],dp[k-1][i-1][j],dp[k-1][i][j-1]);//求最大的 (函数)
dp[k][i][j]+=t;//加上当前位置的好心程度
}
}
}
cout<<dp[n+m][n][n];//输出
return 0;
}