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

P1004 [NOIP2000 提高组] 方格取数

时间:2023-11-14 19:33:19浏览次数:27  
标签:11 NOIP2000 dp1 ty int P1004 取数 && include

P1004 [NOIP2000 提高组] 方格取数

基本思路

我想的是搞两次二维 DP 第一次搞完之后把走过的删掉,然后搞第二次,然而只有 \(80pts\)

#include<iostream>
#include<algorithm>
#include<cstdio>

using namespace std;

int n;
int x, y, t;
int a[11][11];
int dp1[11][11],dp2[11][11];
pair<int , int> g[11][11];

int main()
{
	cin >> n;
	while(cin >> x >> y >> t)
	{
		if (x == 0 && y == 0 && t == 0) break;
		a[x][y] = t;
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			if (dp1[i - 1][j] + a[i][j] > dp1[i][j - 1] + a[i][j])
			{
				dp1[i][j] = dp1[i - 1][j] + a[i][j];
				g[i][j] = {i - 1, j};
			} 
			else 
			{
				dp1[i][j] = dp1[i][j - 1] + a[i][j];
				g[i][j] = {i, j - 1};
			}
		}
	}
	int i = n, j = n, tx, ty;
	a[n][n] = 0;
	while(g[i][j].first != 0 || g[i][j].second != 0)
	{
		tx = g[i][j].first, ty =g[i][j].second;
		a[tx][ty] = 0;
		i = tx, j = ty;	
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			dp2[i][j] = max(dp2[i - 1][j] + a[i][j], dp2[i][j - 1] + a[i][j]);
		}
	}
	cout << dp1[n][n] + dp2[n][n];
	return 0;
}

证伪

理论错误

  • 题意要求两次走过的和最大

    • 即对两次走过整个过程的动态规划
  • 而我的做法是以第一次为第一关键字, 第二次为第二关键字定义下的最大。

    • 即分开对每次动态规划,对总过程实际上是贪心

例子

0 2 1
1 2 0
0 0 0
  • 我的做法
    • 第一次取 $ 2 + 2 = 4$
    • 第二次只能取 \(1\)
    • 总和为 \(5\)
  • 正确做法
    • 第一次取 $2 + 1 = 3 $
    • 第二次取 $ 1 + 2 = 3$
    • 总和为 \(6\)

改进思路

两条路同时动态规划

  • 状态方程

    • \(F_{x_1,y_1,x_2,y_2}\) 表示第一条路走到 \((x_1, y_1)\),第二条路走到 \((x_2, y_2)\)时的最优解。
  • 状态转移

    \[F_{x_1, y_1, x_2, y_2} = \max(F_{x_1 - 1, y_1, x_2 - 1, y_2} , F_{x_1 - 1, y_1, x_2, y_2 - 1} , F_{x_1, y_1 - 1, x_2 - 1, y_2}, F_{x_1, y_1 - 1, x_2, y_2 - 1}) + map_{x_1, y_1} + map_{x_2, y_2} \]

    • 当然,如果两条路走到同一处就会加两次 \(map\),要特判减去一次。

AC代码

#include<iostream>
#include<algorithm>
#include<cstdio>

using namespace std;

int MAX(int a, int b, int c, int d)
{
	return max(max(a,b),max(c,d));
}

int n;
int x, y, t;
int a[11][11];
int F[11][11][11][11];

int main()
{
	cin >> n;
	while(cin >> x >> y >> t)
	{
		if (x == 0 && y == 0 && t == 0) break;
		a[x][y] = t;
	}
	for (int x1 = 1; x1 <= n; x1++)
	{
		for (int y1 = 1; y1 <= n; y1++)
		{
			for (int x2 = 1; x2 <= n; x2++)
			{
				for (int y2 = 1; y2 <= n; y2++)
				{
					F[x1][y1][x2][y2] = MAX(F[x1 - 1][y1][x2 - 1][y2], F[x1 - 1][y1][x2][y2 - 1], F[x1][y1 -1][x2 -1][y2], F[x1][y1 - 1][x2][y2 - 1]) + a[x1][y1] + a[x2][y2];
					if (x1 == x2 && y1 == y2) F[x1][y1][x2][y2] -= a[x1][y1];
				}
			}
		}
	}
	cout << F[n][n][n][n];
	return 0;
}

标签:11,NOIP2000,dp1,ty,int,P1004,取数,&&,include
From: https://www.cnblogs.com/kdlyh/p/17832354.html

相关文章

  • pandas写入和读取数据基本操作
    按行存储数据的二维列表写入数据到Excelimportpandasaspd#定义列表数据data=[['id','姓名','国家'],[1.0,'曹操','魏国'],[2.0,'刘备','蜀国'],[3.0,'孙权','吴国'],[4.0,......
  • python随机抽取数字的方法和代码
    在Python中,我们可以使用内置的random模块来随机抽取数字。下面是一些示例。从一个列表中随机抽取数字如果你有一个数字列表,并且你想从中随机选择一个数字,你可以使用random.choice函数。pythonimportrandomnumbers=[1,2,3,4,5,6,7,8,9,10]chosen_number=rando......
  • C++中获取数组长度
    #include<iostream>usingnamespacestd;template<classT>intlength(T&arr){//cout<<sizeof(arr[0])<<endl;//cout<<sizeof(arr)<<endl;returnsizeof(arr)/sizeof(arr[0]);}intmain(){i......
  • Teamcenter 直接从数据库表取数据的注意要点
    1、如果是取某个类型版本的数据,这种涉及到版本的,一定要主要版次的问题。比如说产品表。签出修改签入后,会产生多个版本。解决方法:版本表,还要拼接  PWORKSPACEOBJECT 的 pactive_seq字段来进行校验 2、日期的问题。比如说取时间表任务的开始和结束时间。......
  • Python进行多线程爬取数据通用模板
    首先,我们需要导入所需的库,包括requests和BeautifulSoup。requests库用于发送HTTP请求,BeautifulSoup库用于解析HTML文档。importrequestsfrombs4importBeautifulSoup然后,我们需要定义一个函数来发送HTTP请求并返回响应。在这个函数中,我们使用requests库的get方法来发送一个GET......
  • Python多线程爬取数据代码模版
    由于对爬虫Ip信息的理解可能存在偏差,我将假设你想要爬取的网站支持Python多线程运行数据。以下是一个简单的Haskell爬虫程序,用于爬取Python多线程跑数据的内容:importNetwork.HTTPimportNetwork.URIimportData.ListimportData.MaybeimportControl.Monad--爬虫爬虫Ip信息......
  • 新手使用nodejs的SerialPort获取数据时需要注意的一个小点
    onData(callback:(data:Buffer)=>void):void{if(this.serialPort!=null){this.serialPort.on("data",(data:Buffer)=>{callback(data);})}}​ 上面的代码相当于当串口接收到数据之后就通知......
  • 嵌入式linux SD读取数据导致死机问题
    一、碰到的问题通过ssh命令将文件写入到SD卡中,发现有一张SD卡(金士顿)可以成功写入,而另一张SD(闪迪)一直写入失败。应用层读取文件时,有一张SD卡(金士顿)可以成功读取数据;另一张SD卡(闪迪)有很大的概率会导致司机。二、SD卡驱动硬件电路图1.SD卡驱动硬件电路三、调试过程查看......
  • Angular 应用如何从 Transfer State 状态中读取数据
    在Angular应用程序中,数据的传递和共享是一个重要的问题。Angular提供了多种机制来处理这个问题,其中之一就是TransferState机制。本文将深入探讨上述代码中的AngularTransferState的用法,并介绍如何在Angular应用中有效地利用它。AngularTransferState简介AngularTransferS......
  • Java基础 字节输入流 读取数据 的两个方法API
    public int read()  →  一次读取一个字节数据public int read(byte[] buffer)  →  一次读取一个字节数组的数据,每次读取都会尽可能把数组装满我们创建的数组的长度尽量是1024的整数倍,例如1024*1024*5的长度 ......