这题我是用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;
}
如下: