luogu1004 【2000提高】方格取数(dp)

本文介绍了一种使用动态规划解决特定场景下重复路径计数问题的方法,通过优化算法复杂度,将原始O(n^4)的时间复杂度降低到O(n^3)。该问题涉及从起点到终点的所有可能路径中寻找不重复的路径数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这水题我居然还想了半天。。傻死我自己得了。首先要明确,两次从(1,1)走到(n,n)都需要走2*n步。所以可以两次一起走。对于一个点(m,n)两次都只可能在走第m+n步时经过,所以只需在当次判断是否重复,其他时候都绝对不会重复。朴素的是dp[x1][y1][x2][y2],第一次走到x1,y1,第二次走到x2,y2.O(n4),优化一下,dp[k][i][j],走到第i步了,第一次向下走了i步,第二次向下走了j步,则向右走了k-j步。O(n3)。。反正n==9,随意啦

#include <cstdio>
#include <cstring>
#define N 10
int n,a[N][N],dp[N<<1][N][N];
inline int max(int x,int y){return x>y?x:y;}
int main(){
//  freopen("a.in","r",stdin);
    scanf("%d",&n);
    while(1){
        int x,y,val;
        scanf("%d%d%d",&x,&y,&val);
        if(x==0) break;
        a[x][y]=val;
    }
    for(int k=1;k<=n*2;++k)//一次走了k步。 
        for(int i=1;i<=k&&i<=n;++i)//第一次向下走了i步 
            for(int j=1;j<=k&&j<=n;++j){//第二次向下走了j步 
                dp[k][i][j]=max(max(dp[k-1][i-1][j-1],dp[k-1][i][j-1]),max(dp[k-1][i][j],dp[k-1][i-1][j]));
                dp[k][i][j]+=a[i][k-i];
                if(i!=j) dp[k][i][j]+=a[j][k-j];
            }
    printf("%d\n",dp[n*2][n][n]);
    return 0;

}
#include<bits/stdc++.h> using namespace std; int n,x,y,z,a[10][10],f[10][10][10][10]; int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>x>>y>>z; a[x][y]=z; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) for(int l=1;l<=n;l++) 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]+(i!=k||j!=l)*a[k][l]; cout<<f[n][n][n][n]; return 0; } 代码如上,题目如下 # P1004 [NOIP 2000 提高组] 方格 ## 题目背景 NOIP 2000 提高组 T4 ## 题目描述 设有 $N \times N$ 的方格图 $(N \le 9)$,我们将其中的某些方格中填入正整,而其他的方格中则放入字 $0$。如下图所示(见样例): ![](https://cdn.luogu.com.cn/upload/image_hosting/0bpummja.png) 某人从图的左上角的 $A$ 点出发,可以向下行走,也可以向右走,直到到达右下角的 $B$ 点。在走过的路上,他可以方格中的走后的方格中将变为字 $0$)。 此人从 $A$ 点到 $B$ 点共走两次,试找出 $2$ 条这样的路径,使得得的之和为最大。 ## 输入格式 输入的第一行为一个整 $N$(表示 $N \times N$ 的方格图),接下来的每行有三个整,前两个表示位置,第三个为该位置上所放的。一行单独的 $0$ 表示输入结束。 ## 输出格式 只需输出一个整,表示 $2$ 条路径上得的最大的和。 ## 输入输出样例 #1 ### 输入 #1 ``` 8 2 3 13 2 6 6 3 5 7 4 4 14 5 2 21 5 6 4 6 3 15 7 2 14 0 0 0 ``` ### 输出 #1 ``` 67 ``` ## 说明/提示 据范围:$1\le N\le 9$。
最新发布
08-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值