zoukankan      html  css  js  c++  java
  • 洛谷P1006 传纸条

    题目链接:https://www.luogu.com.cn/problem/P1006

    就是从左上到右下,取两条不相交路径,使得总分值最大设f[i][j][k][l]表示第一次走到(i,j),第二次走到(k,l)的最大分值,则有:1)若不在起点或终点,且i=k,j=l,说明两次走到了不在起点或终点的同一个位置,此时f[i][j][k][l]=-inf;2)否则 f[i][j][k][l]=max(f[i-1][j][k-1][l],f[i][j-1][k-1][l],f[i-1][j][k][l-1],f[i][j-1][k][l-1])+a[i][j]+a[k][l],意思就是两次分别都从前一个格子转移而来,每个之前的格子可以向右或向下走,会产生4种转移,最后加上a[i][j]和a[k][l]当前格子的值

    我一开始写的转移方程是:1)若不在起点或终点,且i=k,j=l,说明两次走到了不在起点或终点的同一个位置,此时f[i][j][k][l]=-inf;2)f[i][j][k][l]=max(f[i-1][j][k][l]+a[i][j],f[i][j-1][k][l]+a[i][j],f[i][j][k-1][l]+a[k][l],f[i][j][k][l-1]+a[k][l]);但是实际操作了一下发现这个方程会走重复的路径,其实就是把最长的路径走了两遍。然后又改成了上面的方程。现在还在想严格说明为什么上面的方程可以保证路径可以保证路径不相交,但是这个不可以呢?这个我只能感觉一下............留个坑待填吧

    正解代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=55;
     4 const int inf=0x3f3f3f3f;
     5 int a[maxn][maxn],f[maxn][maxn][maxn][maxn];
     6 int m,n,i,j,k,l,t;
     7 
     8 int main(){
     9     freopen("luogu1006.txt","r",stdin);
    10     cin>>m>>n;
    11     for (i=1;i<=m;i++)
    12       for (j=1;j<=n;j++) cin>>a[i][j];
    13     memset(f,0,sizeof(f));
    14     for (i=1;i<=m;i++)
    15       for (j=1;j<=n;j++)
    16         for (k=1;k<=m;k++)
    17           for (l=1;l<=n;l++){
    18               if (i==1&&j==1&&k==1&&l==1) continue;
    19               if ((i==k&&j==l)&&(!(i==m&&j==n&&k==m&&l==n))) { //不是终点 ,同一位置
    20                   f[i][j][k][l]=-inf;continue;             
    21         }
    22         t=max(max(f[i-1][j][k-1][l],f[i-1][j][k][l-1]),max(f[i][j-1][k-1][l],f[i][j-1][k][l-1])); //*
    23         f[i][j][k][l]=t+a[i][j]+a[k][l]; 
    24     }
    25     cout<<f[m][n][m][n]<<endl;
    26     fclose(stdin);
    27     return 0;
    28 }
    洛谷1006_1

    从进阶指南上看到还有一种巧妙一些的状态设计,把维数降到3。设f[i][j][k]表示每次走了i步,第一次走到第j行,第二次到第k行能得到的最大值。由于在第j行走i步,所以第一次走到(j,i+2-j),同理第二次走到(k,i+2-k)。则有转移方程:1)若i≠n+m-2且j=k,则f[i][j][k]=-inf;2)f[i][j][k]=max(f[i-1][j-1][k-1],f[i-1][j][k-1],f[i-1][j-1][k],f[i-1][[j][k])+a[j,i+2-j]+a[k,i+2-k]。和第一个方程一样,这儿max()里的四个值也表示由4种之前的状态转移得到当前状态

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=50+5;
     4 const int inf=0x3f3f3f3f;
     5 int a[maxn][maxn];
     6 int f[maxn*2][maxn][maxn];
     7 int n,m,i,j,k,t;
     8 
     9 int main(){
    10     //freopen("luogu1006.txt","r",stdin);
    11     cin>>n>>m;
    12     for (i=1;i<=n;i++)
    13       for (j=1;j<=m;j++) cin>>a[i][j];
    14     memset(f,0,sizeof(f));
    15     for (i=1;i<=n+m-2;i++)
    16       for (j=1;j<=n;j++)
    17         for (k=1;k<=n;k++)
    18           if ((i+2>j)&&(i+2>k)){
    19                if (i!=n+m-2&&j==k){ //不是终点,且走到同一位置 
    20                    f[i][j][k]=-inf;continue;
    21                }
    22                      f[i][j][k]=max(max(f[i-1][j-1][k-1],f[i-1][j][k-1]),max(f[i-1][j-1][k],f[i-1][j][k]))+a[j][i+2-j]+a[k][i+2-k]; 
    23           }
    24     cout<<f[n+m-2][n][n]<<endl;
    25     //fclose(stdin);
    26     return 0;
    27 }
    洛谷1006_2

     

  • 相关阅读:
    Day22:异常处理、socke基于TCP协议编程
    Day21:面向对象的软件开发、反射、对象的内置方法
    Day20:绑定方法与非绑定办法、多态和多态性
    Day19:继承实现的原理、子类中调用父类的方法、封装
    Day18:类的抽象、类的组合应用
    Day17:类的继承、派生、组合和接口
    Day16:面向对象编程——类和对象
    数据结构
    python爬虫篇之 性能相关
    scrapy-redis
  • 原文地址:https://www.cnblogs.com/edmunds/p/12670157.html
Copyright © 2011-2022 走看看