zoj 2710 Two Pipelines

本文探讨了使用动态规划(DP)和贪心算法解决城市管道问题的策略,详细介绍了两种方法的实现过程及优缺点。通过比较不同算法在实际应用中的表现,为读者提供了有效的解决方案。

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

    这题我是用dp过的,回头看了网上的资料,可以用谈心。再想想吧,先保存以下代码:

/*
 * zoj_2710.cpp
 */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;

#define	N	210
#define INF	1e12

/*
 * dp[i][x][y]: The state is x:pipeline1 and y:pipeline2, after decising the ith city.
 */
double dp[2][N][N];		
double cost[N][2];
bool decision[N][N][N];
int n, c;
struct Point {
	int x, y;
};
Point pipe0[2], pipe1[2];
Point city[N];
int demand[N];

inline double cross_dis( int x0, int y0, int x, int y )
{
	return fabs( double( x0*y-x*y0 ) )/sqrt( double(x0*x0+y0*y0) );
}

inline double func_cost( int idx, int which ) {
	Point pt0, pt1, pt;
	double d;
	if ( 0 == which ) {
		pt0 = pipe0[0];
		pt1 = pipe0[1];
	}
	else if ( 1 == which ) {
		pt0 = pipe1[0];
		pt1 = pipe1[1];
	}
	pt = city[idx];

	/*	
	if ( point_multi( pt0, pt1, pt ) == false ) { 	//<0
		d = distance( &pt0, &pt );
	}
	else if ( point_multi( pt1, pt0, pt ) == false ) { //<0
		d = distance( &pt1, &pt );
	}
	*/

	d = cross_dis( pt1.x-pt0.x, pt1.y-pt0.y, pt.x-pt0.x, pt.y-pt0.y );

	return ( d * demand[idx] );
}

void print_ans( int i, int x ) {	//x: pipeline1 count
	if ( i < 1 )
		return;

	if ( decision[i][x][i-x] ) {
		print_ans( i-1, x );
		printf("2 ");
	}
	else {
		print_ans( i-1, x-1 );
		printf("1 ");
	}		
}

int main()
{
	int i, k, x, y, a;
	double tmp0, tmp1, min;

	while ( scanf("%d%d", &n, &c ) != EOF ) {
		scanf("%d%d%d%d", &pipe0[0].x, &pipe0[0].y, &pipe0[1].x, &pipe0[1].y );
		scanf("%d%d%d%d", &pipe1[0].x, &pipe1[0].y, &pipe1[1].x, &pipe1[1].y );
		for ( i = 1; i <= n; ++ i ) {
			scanf("%d%d%d", &city[i].x, &city[i].y, &demand[i] ); 
		}

		memset( dp[0], 0, sizeof(dp[0]) );
		a = 0;
		for ( i = 1; i <= n; ++ i ) {

			cost[i][0] = func_cost( i, 0 );
			cost[i][1] = func_cost( i, 1 );

			dp[1-a][0][i] = dp[a][0][i-1] + cost[i][1];
			decision[i][0][i] = true;

			dp[1-a][i][0] = dp[a][i-1][0] + cost[i][0];
			decision[i][i][0] = false;

			for ( x = 1; x < i; ++ x ) {
				y = i - x;
				tmp0 = dp[a][x-1][y] + cost[i][0];
				tmp1 = dp[a][x][y-1] + cost[i][1];	
				if ( tmp1 > tmp0 ) {
					dp[1-a][x][y] = tmp0;
					decision[i][x][y] = false;
				}
				else {
					dp[1-a][x][y] = tmp1;
					decision[i][x][y] = true;
				}
			}
			a = 1 - a;
		}

		min = INF;
		for ( x = 0; x <= n; ++ x ) {
			y = n-x;
			if ( abs(x-y) <= c && dp[a][x][y] <= min ) {
				min = dp[a][x][y];
				k = x;
			}
		}

		if ( decision[n][k][n-k] ) {		//pipeline1
			print_ans( n-1, k );
			printf("2\n");
		}
		else {
			print_ans( n-1, k-1 );
			printf("1\n");
		}
	}
	return 0;
}

    回宿舍又想了一下,使用贪心,代码

/*
 * zoj_2710_2.cpp
 * greedy codes
 */

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;

#define N 	210
#define eps	1e-9

struct Node {
	double dis;
	unsigned char decision;
	short idx;
};
Node node[N];
struct Point {
	int x, y;
};
Point pipe0[2], pipe1[2];
short ans[N];
int n, c;

inline double cross_dis( int x0, int y0, int x, int y )
{
	return fabs( double( x0*y-x*y0 ) )/sqrt( double(x0*x0+y0*y0) );
}
inline double dis( int x, int y, int which ) {
	Point pt0, pt1;
	double d;
	if ( 0 == which ) {
		pt0 = pipe0[0];
		pt1 = pipe0[1];
	}
	else if ( 1 == which ) {
		pt0 = pipe1[0];
		pt1 = pipe1[1];
	}
	d = cross_dis( pt1.x-pt0.x, pt1.y-pt0.y, x-pt0.x, y-pt0.y );
	return ( d );
}

int cmp( Node const& a, Node const& b )
{
	return ( a.dis+eps < b.dis );
}

int main()
{
	int i, x, y, k, demand, tmp;
	double tmp0, tmp1;

	while ( scanf("%d%d", &n, &c ) != EOF ) {
		scanf("%d%d%d%d", &pipe0[0].x, &pipe0[0].y, &pipe0[1].x, &pipe0[1].y );
		scanf("%d%d%d%d", &pipe1[0].x, &pipe1[0].y, &pipe1[1].x, &pipe1[1].y );
		for ( i = 1; i <= n; ++ i ) {
			scanf("%d%d%d", &x, &y, &demand ); 
			
			tmp0 = dis(x,y,0);
			tmp1 = dis(x,y,1);	
			if ( tmp0 > tmp1 ) {
				node[i].decision = 1;
			}
			else	{
  				node[i].decision = 0;
			}
			node[i].dis = fabs( tmp0-tmp1 ) * demand; 
			node[i].idx = i;
		}
			
		sort( node+1, node+n+1, cmp );	
		x = y = 0;
		for ( i = 1; i <= n; ++ i ) {
			if ( 0 == node[i].decision )
				++ x;
			else
				++ y;
		}
		if ( abs(x-y) > c ) {
			if ( x > y )
				tmp = 0;					
			else	
				tmp = 1;
			k = (abs(x-y)-c+1)/2;
			for ( i = 1; i <= n; ++ i ) {
				if ( node[i].decision == tmp ) {
					node[i].decision = 1-tmp;
					-- k;
				}	//注意这里,不能单纯的把前k个decision反转。这里卡了一下。
				if ( 0 == k )
					break;
			}	
		}
		for ( i = 1; i <= n; ++ i )
			ans[ node[i].idx ] = node[i].decision+1;
		for ( i = 1; i < n; ++ i )
			printf("%d ", ans[i] );
		printf("%d\n", ans[i] );
	}
	return 0;
}

如下:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值