首页 > 其他分享 >P1004 [NOIP2000 提高组] 方格取数

P1004 [NOIP2000 提高组] 方格取数

时间:2024-12-09 15:31:37浏览次数:4  
标签:vector 101 NOIP2000 int P1004 取数 num include DP

题目描述

设有 N×N 的方格图 (N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 0。如下图所示(见样例):

某人从图的左上角的 A 点出发,可以向下行走,也可以向右走,直到到达右下角的 B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0)。
此人从 A 点到 B 点共走两次,试找出 2 条这样的路径,使得取得的数之和为最大。

输入格式

输入的第一行为一个整数 N(表示 N×N 的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的 0 表示输入结束。

输出格式

只需输出一个整数,表示 2 条路径上取得的最大的和。

输入输出样例

输入 #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≤N≤9。

题解:

        看着很简单的一道题,数据范围也很小,这多美好啊是吧。

        看完题,因为知道是动态规划的题就直接上了一个一维的DP,DP[i]来记录到maps[i][i]的最大的和,就是一条支路的最优解,然后再通过记录的路线,更改原始maps,然后再DP一遍就好了。看着挺不错的,但是问题就出在这。一次最优不一定二次最优,这个方法使用了贪心的策略,所以很可惜,最后有两个样例过不了。

        后来改了几个方案,但是最多只有二维的DP,所以还是过不了。

        偷偷看了一眼题解,发现原来是要用四维的DP,其中DP[i][j][k][h]是到[i][j]的第一条路和到[k][h]的第二条路的和,及题目的答案。有点难想到。

        状态转移方程:

DP[i][j][k][h]=max(max(DP[i-1][j][k-1][h],DP[i-1][j][k][h-1]),max(DP[i][j-1][k-1][h],DP[i][j-1][k][h-1]))

        要注意当i==k,j==h的时候多加了一格要减去。 

        令外说一句,这题回溯法更简单。

代码:

 一维/二维+贪心代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;

int n=0,i,j,k;
vector<vector<int>> maps(101,vector<int>(101,0));
int x=0,y=0,num=0;
vector<int> dp(101,0);
vector<vector<int>> road(101,vector<int>(101,0));
int ans=0;

int main(){
    cin >> n;
    while(true){
        cin >> x >> y >> num;
        if(x==0 && y==0 && num==0){
            break;
        }
        maps[x][y]=num;
    }
    dp[1]=maps[1][1];
    for(i=2;i<=n;i++){
        int t=0,t1=0,t2=0,maxt=0;
        for(j=1;j<i;j++){
            t1=dp[j];
            t2=dp[j];
            for(k=j+1;k<=i;k++){
                t1+=maps[k][j];
                t1+=maps[i][k];
                t2+=maps[j][k];
                t2+=maps[k][i];
            }
            t=max(t1,t2);
            //cout << t1 << " " << t2 << "\n";
            if(maxt<=t){
                road[i][0]=j;
                if(t1>=t2){
                    road[i][1]=1;
                }
                else{
                    road[i][1]=2;
                }
            }
            maxt=max(maxt,t);
        }
        dp[i]=maxt;
    }
    ans=dp[n];
    //cout << ans << "\n";
    /*
    for(i=1;i<=n;i++){
        cout << road[i][0] << " " << road[i][1] << "\n";
    }
    */
    if(n==1){
        cout << ans << "\n";
        return 0;
    }
    int nn=n;
    while(nn!=1){
        int t1=road[nn][0];
        int t2=road[nn][1];
        if(t2==1){
            for(i=t1;i<=nn;i++){
                maps[i][t1]=0;
                maps[nn][i]=0;
            }
        }
        else if(t2==2){
            for(i=t1;i<=nn;i++){
                maps[t1][i]=0;
                maps[i][nn]=0;
            }
        }
        nn=t1;
    }
    /*
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            cout << maps[i][j] << " ";
        }
        cout << "\n";
    }
    */
    dp[1]=maps[1][1];
    for(i=2;i<=n;i++){
        int t=0,t1=0,t2=0,maxt=0;
        for(j=1;j<i;j++){
            t1=dp[j];
            t2=dp[j];
            for(k=j+1;k<=i;k++){
                t1+=maps[k][j];
                t1+=maps[i][k];
                t2+=maps[j][k];
                t2+=maps[k][i];
            }
            t=max(t1,t2);
            maxt=max(maxt,t);
        }
        dp[i]=maxt;
    }
    ans+=dp[n];
    cout << ans << "\n";
    return 0;
}

四维DP代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<stack>
#include<vector>
#include<unordered_set>
#include<unordered_map>
#include<map>
#include<set>
using namespace std;
typedef long long int ll;

int n=0,i,j,k,h;
vector<vector<int>> maps(101,vector<int>(101,0));
int x=0,y=0,num=0;
int ans=0;
int dp[101][101][101][101];

int main(){
    cin >> n;
    while(true){
        cin >> x >> y >> num;
        if(x==0 && y==0 && num==0){
            break;
        }
        maps[x][y]=num;
    }
    for(i=1;i<=n;i++){
        for(j=1;j<=n;j++){
            for(k=1;k<=n;k++){
                for(h=1;h<=n;h++){
                    int t1=max(dp[i-1][j][k-1][h],dp[i-1][j][k][h-1]);
                    int t2=max(dp[i][j-1][k-1][h],dp[i][j-1][k][h-1]);
                    dp[i][j][k][h]=max(t1,t2)+maps[i][j]+maps[k][h];
                    if(i==k && j==h){
                        dp[i][j][k][h]-=maps[i][j];
                    }
                }
            }
        }
    }
    cout << dp[n][n][n][n] << "\n";
    return 0;
}

 

标签:vector,101,NOIP2000,int,P1004,取数,num,include,DP
From: https://blog.csdn.net/2301_78848414/article/details/144347886

相关文章

  • 绝区零1.3菲林获取数量介绍
    绝区零1.3版本能拿多少菲林?绝区零1.3版本即将于三日后更新了,每个版本我们都可以拿到一些免费的菲林,不同阶段的玩家可获取的菲林数量不一样,小编给大家计算了一下1.3可以获得的菲林数量,一起来看看吧! 绝区零1.3菲林获取数量介绍零氪:8530~11010*菲林小月卡:12310~15390*菲林大小......
  • P10046 [CCPC 2023 北京市赛] 哈密顿(贪心)
    题意给定\(2n\)个点,第\(i(1\lei\len)\)个点的点权为\(a_i\),第\(j(n<j\le2n)\)个点的点权为\(b_i\),对于每个\(i,j(1\lei\len<j\le2n)\),在\(i,j\)间连一条边,边权为\(|a_i-b_j|\)。定义一条路径的权值为经过的边的边权之和,求权值最大的哈密顿回路。\(n\le10^5\)......
  • 使用MATLAB从Excel文件读取数据并绘制堆叠柱状图
    在数据可视化中,堆叠柱状图是展示多个变量相对比例的非常有效的方法。它通过将每个数据系列堆叠在一起,帮助我们理解不同数据类别在总量中所占的份额。在这篇博客中,我们将学习如何使用MATLAB从Excel文件导入数据,并使用渐变色来绘制堆叠柱状图。我们还将探索如何选择和调整颜色,使......
  • 1402 区间取数2
    //1402区间取数2.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。///*http://oj.daimayuan.top/course/22/problem/1090给你n个数a1,a2,...,an和一个整数k,你需要在这n个数中选出连续一段数,使得这些数的和不超过k。请问最多能选几个数。输入格式......
  • 1401 区间取数1
    //1401区间取数1.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。///*http://oj.daimayuan.top/course/22/problem/1089给你n个数a1,a2,...,an和一个整数k,你需要在这n个数中选出连续的c个数,使得这c个数的最大值不超过k,请问有几种选法。输入格式......
  • Python爬虫:获取数据的入门详解
    在互联网时代,数据已成为最宝贵的资源之一。Python,作为一种功能强大且易于学习的编程语言,成为了数据获取和处理的理想工具。Python爬虫,特别是,允许我们从网页中自动提取大量数据,为数据分析、机器学习、研究和开发等多种应用提供了原材料。本文将为您提供一个Python爬虫的入门详解......
  • <<迷雾>> 第11章 全自动加法计算机(6)--一只开关取数 示例电路
    用一只开关依次将数取出info::操作说明刚启动时,t0=1,t1=t2=0,此时只有IAR`=1.按下开关K不要松开,地址寄存器AR收到一个上升沿信号,保存住当前地址,并提供给存储器(注:第一个地址为0,所以电路中暂看不出什么变化)松开开关K,循环移位计数器RR得到......
  • datatables使用ajax获取数据
    前端://初始化datatablevartable3=$('.jiaoshi_lst').DataTable({"processing":true,"serverSide":true,"paging":true,"ordering":false,"searching":false......
  • 【接口自动化测试】jsonpath应用:提取数据、断言、接口关联
    安装命令pipinstalljsonpath表达式importjsonpathres=jsonpath.jsonpath(obj,expr)1、返回结果要么是list,要么是False2、obj 要提取的对象,应为字典类型。报文的格式是json,必须进行数据的转换, 用json.loads()将json转换成字典类型   expr jsonpath表......
  • 【油猴脚本】00011 案例 Tampermonkey油猴脚本,动态渲染表格-实现页面动态-添加提取数
    前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦......