UVa 1336 Fixing the Great Wall

The Great Wall of China is truly one of the greatest wonders of the world. In 3-rd century BC, Emperor Qin Shi Huang connected the defensive structures built earlier by the states of Qin, Yan, and Zhao kingdoms. The purpose of the wall was to defend against raids by the barbarians from Mongolia and Manchuria. The wall was extended and renovated in later centuries, creating an impressive 6,700 km long fortification.

The centuries have left their mark on the wall, there are several sections that need immediate renovation. These sections have to be repaired as soon as possible since they deteriorate every day: if we do not fix them now, it will be more expensive to repair them later. Thus the Ministry of Monuments have designed and built the world's first Great Wall Automatic Repair Robot (GWARR), to repair the damaged sections (we are in the 21-st century, aren't we?) Your task is to write the software that will guide the robot and decide the order in which the sections are to be repaired.

For the purpose of this problem, we assume that the Great Wall is a long straight line, and every location on the wall is identified by a single number (say, the distance from one end). The GWARR is placed at some location on the wall and it can move with constant speed in both directions. For each damaged section you are given its location, how much it would cost to repair now, and how the cost would increase if repaired later. The GWARR works so efficiently that once it is at the exact location of the damaged section it can repair the wall immediately.

Input 

The input contains several blocks of test cases. Each case begins with a line containing three integers: an integer 1$ \le$n$ \le$1000, the number of damaged sections, an integer 1$ \le$v$ \le$100, the speed of the GWARR in distance units/time units, and an integer 1$ \le$x$ \le$500000, the initial position of the GWARR. The next n lines describe the n damaged sections that have to be repaired. Each line contains three integers: the location 1$ \le$x$ \le$500000 of the section, the cost 0$ \le$c$ \le$50000 of repairing it immediately, and 1$ \le$$ \Delta$$ \le$50000, the increase in cost per time unit. Therefore, if the section is repaired after t time units have passed, then we have to pay c + t$ \Delta$ units of money. It can be assumed that the locations of the sections are all different, and the initial location of the robot is not on the list of damaged seetions.

The input is terminated by a test case with n = v = x = 0.

Output 

For each test case, you have to output a line containing a single number, the minimum cost of repairing the wall. This number should be an integer, round down the result, if necessary. It can be assumed that the minimum cost is not more than 1000000000.

In the optimum solution for the first test case below, we first fix loeation 998 at the cost of 600, then the location 1010 at the cost of l400, and finally we fix the location 996 at the cost of 84, giving the total cost 2084.

Sample Input 

3 1 1000
1010 0 100
998 0 300
996 0 3
3 1 1000
1010 0 100
998 0 3
996 0 3
0 0 0

Sample Output 

2084
1138
 
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

// record[i][j][0]代表现在在点i, 修复第1,...,i-1,j,,,,n点需要的最少花费
// record[i][j][1]代表现在在点j, 修复第1,...,i,j+1,,,,n点需要的最少花费
double record[1010][1010][2];
int flag[1010][1010][2];
// 修复点结构体
typedef struct node
{
	double x;	// 修复点位置
	double cost;	// 修复点花费价格
	double ratio;	// 修复点的每单位时间增长价格
	bool operator < (const struct node& s) const
	{
		return x < s.x;
	}
}node;

node array[1100];


int n;
double x;
double v;

double get_cost(int i, int j, double time);
double get_min(int i, int j, int k);


// cost_sum[i]代表第1,...,i的速率之和
double cost_sum[1100];

int c_count;

int main()
{
	memset(flag, 0, sizeof(flag));
	c_count = 1;	
	while(scanf("%d %lf %lf", &n, &v, &x) == 3 && !(n == 0 && v == 0 && x == 0))
	{
//		memset(record, 0, sizeof(record));
//		memset(flag, 0, sizeof(int)*(n*n*2));
		// 读入情况
		for(int i = 1; i <= n; i++)
		{
			scanf("%lf %lf %lf", &array[i].x, &array[i].cost, &array[i].ratio);
		}		

		// 修复点按位置从小到大排序
		sort(array+1, array+1+n);

		// 计算速率之和
		cost_sum[0] = 0;
		for(int i = 1; i <= n; i++)
			cost_sum[i] = cost_sum[i-1] + array[i].ratio;
		
		// 找到起始的位置
		int p1 = 0, p2 = 0;
		if(x < array[1].x)
		{
			p1 = 0;
			p2 = 1;
		}
		else if(x > array[n].x)
		{
			p1 = n;
			p2 = n+1;
		}
		else
		{
			for(int i = 1; i <= n-1; i++)
			{
				if(array[i].x < x && array[i+1].x > x)
				{
					p1 = i;
					p2 = i+1;
					break;
				}	
			}
		}	


//		printf("p1: %d p2: %d\n", p1, p2);

		double r1, r2;
		if(p1 >= 1 && p1 <= n)
		{
			r1 = get_cost(1,2, (x-array[p1].x)/v);
		}	
		if(p2 >= 1 && p2 <= n)
		{
			r2 = get_cost(1,2, (array[p2].x-x)/v);
		}

//		printf("r1: %lf  r2: %lf\n", r1, r2);
	
		// 计算结果
		double ans, a1, a2;
		if(x < array[1].x)
		{
			ans = r2 + array[1].cost + get_min(p1, p2, 1);
		}			
		else if(x > array[n].x)
		{
			ans = r1 + array[n].cost + get_min(p1, p2, 0);
		}
		else
		{
			a1 = r1 + array[p1].cost + get_min(p1, p2, 0);
			a2 = r2 + array[p2].cost + get_min(p1, p2, 1);
//			printf("a1: %lf, a2: %lf\n", a1, a2);
			ans = min(a1, a2);
		}
		printf("%.0f\n", floor(ans));
		c_count++;	
	}
	return 0;		
}


// 计算第1,...,i, j,...,n的所有点在time时间里产生的花费
double get_cost(int i, int j, double time)
{
/*
	double sum = 0;
	
	for(int k = 1; k <= i; k++)
		sum += array[k].ratio * time;
	
	for(int k = j; k <= n; k++)
		sum += array[k].ratio * time;

	return sum;	
*/

	double sum = 0;
	if(i < 1 && j > n)
		sum = 0;
	else if(i < 1 && j <= n)
		sum = cost_sum[n] - cost_sum[j-1];
	else if(i >= 1 && j > n)
		sum = cost_sum[i];
	else
		sum = cost_sum[n] - (cost_sum[j-1] - cost_sum[i]);
	return sum*time;	

}

// 计算结果
// record[i][j][0]代表现在在点i, 修复第1,...,i-1,j,,,,n点需要的最少花费
// record[i][j][1]代表现在在点j, 修复第1,...,i,j+1,,,,n点需要的最少花费
double get_min(int i, int j, int k)
{
	if(flag[i][j][k] == c_count)
//	if(flag[i][j][k] == 1)
		return record[i][j][k];
	
	flag[i][j][k] = c_count;
	if(i == 0 && j == n+1)
	{
		record[i][j][k] = 0;
		return record[i][j][k];
	}	

	// 如果待修的点是i-1或j
	if(k == 0)	
	{
		double r1 = -1, r2 = -1;
		if(i-1 >= 1)
			r1 = get_cost(i-1, j, (array[i].x-array[i-1].x)/v);
		if(j <= n)
			r2 = get_cost(i-1, j, (array[j].x-array[i].x)/v);

		double a1 = -1, a2 = -1;
		if(r1 != -1)
			a1 = r1 + array[i-1].cost + get_min(i-1, j, 0);
		if(r2 != -1)
			a2 = r2 + array[j].cost + get_min(i-1, j, 1);
		
		double ans;
		if(a1 == -1 && a2 != -1)		
			ans = a2;
		else if(a1 != -1 && a2 == -1)
			ans = a1;
		else if(a1 != -1 && a2 != -1)
			ans = min(a1, a2);
		else
			ans = 0;	
		record[i][j][k] = ans;
		return record[i][j][k];		
	}	
	// 如果待修的点是i,j+1
	else
	{
		double r1 = -1, r2 = -1;
                if(i >= 1)
                        r1 = get_cost(i, j+1, (array[j].x-array[i].x)/v);
                if(j+1 <= n)
                        r2 = get_cost(i, j+1, (array[j+1].x-array[j].x)/v);

                double a1 = -1, a2 = -1;
                if(r1 != -1)
                        a1 = r1 + array[i].cost + get_min(i, j+1, 0);
                if(r2 != -1)
                        a2 = r2 + array[j+1].cost + get_min(i, j+1, 1);

                double ans;
                if(a1 == -1 && a2 != -1)
                        ans = a2;
                else if(a1 != -1 && a2 == -1)
                        ans = a1;
                else if(a1 != -1 && a2 != -1)
                        ans = min(a1, a2);
		else
			ans = 0;
                record[i][j][k] = ans;
                return record[i][j][k];
	}
}


 
这题动态规划不难想,在刚开始,机器人必定是在可能的两侧2个最近的点(如果有的话)选一个地点进行修复。然后再从可能的两侧2个最近的点来修复。
由于题目中n可以达到1000. 于是就想到开这样大的数组,最多为n^2级别。所以构思状态为d(i,j,k).
k = 0时代表已修复了i,i+1,...,j-1,修复剩余的点所花最小花费
k = 1时代表已修复了i+1,...,j,修复剩余的点所花最小花费
(这样的状态表示是不得已而为之)。
这题的要求很死,很容易TLE. 
学习到了:
1. 如果记忆化搜索不能memset, 那么只能用flag标记,并且对每一轮count的序号进行标记。
2. 能算的尽量先算好,比如get_cost函数。
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值