百度之星1002

双调旅行商问题


Disk Schedule

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2013    Accepted Submission(s): 274


Problem Description
 
   
有很多从磁盘读取数据的需求,包括顺序读取、随机读取。为了提高效率,需要人为安排磁盘读取。然而,在现实中,这种做法很复杂。我们考虑一个相对简单的场景。 磁盘有许多轨道,每个轨道有许多扇区,用于存储数据。当我们想在特定扇区来读取数据时,磁头需要跳转到特定的轨道、具体扇区进行读取操作。为了简单,我们假设磁头可以在某个轨道顺时针或逆时针匀速旋转,旋转一周的时间是360个单位时间。磁头也可以随意移动到某个轨道进行读取,每跳转到一个相邻轨道的时间为400个单位时间,跳转前后磁头所在扇区位置不变。一次读取数据的时间为10个单位时间,读取前后磁头所在的扇区位置不变。磁头同时只能做一件事:跳转轨道,旋转或读取。 现在,需要在磁盘读取一组数据,假设每个轨道至多有一个读取请求,这个读取的扇区是轨道上分布在 0到359内的一个整数点扇区,即轨道的某个360等分点。磁头的起始点在0轨道0扇区,此时没有数据读取。在完成所有读取后,磁头需要回到0轨道0扇区的始点位置。请问完成给定的读取所需的最小时间。
 

Input
 
   
输入的第一行包含一个整数M(0
 

Output
 
   
对于每组测试数据,输出一个整数,表示完成全部读取所需的时间。
 

Sample Input
 
   
3 1 1 10 3 1 20 3 30 5 10 2 1 10 2 11
 

Sample Output
 
   
830 4090 1642


算法详解


http://blog.csdn.net/xiaofengcanyuexj/article/details/26081833


我自己的代码(1A)

#include 
#include 
using namespace std;

#define MAX 1010
#define INF 1000000000


int n, i, j, k, sum, ans;
int x[MAX], dis[MAX][MAX] ,dp[MAX][MAX];

inline int min(int a, int b)
{
    return a < b ? a : b;
}

void read()
{

    scanf("%d",&n);
    x[0] = 0;
    for(i = 1; i <= n; i++ )
    {
        scanf("%d%d",&sum, &x[i]);
    }
    for(i = 0; i <= n; i++ )
    {
        for(j = 1; j <= n; j++ )
        {
            dis[i][j] = min( abs( x[i] - x[j]), 360 - ( abs( x[i] - x[j] ) ) );
        }
    }


}

void init( int n )
{
    for(i = 0; i <= n; i++ )
    {
        for(j = 0; j <= n; j++)
        {
            dp[i][j] = INF;
        }
    }
}

void dpsolve()
{
    
    dp[0][0] = 0;
    for(i = 1; i <= n; i++)
    {
        for(j = 0; j <= i; j++)
        {
            if( j < i - 1 ) dp[i][j] = dp[ i - 1 ][j] + dis[ i - 1 ][i];
            else if(j == i - 1)
            {
                for(k = 0; k <= j; k++)
                {
                    dp[i][j] = min( dp[i][j], dp[j][k] + dis[k][i]);
                }
            }
            else 
            {
                for(k = 0; k < j; k++)
                {
                    dp[i][i] = min( dp[i][i], dp[i][k] + dis[k][i] );
                }
            }
        }
    }
    ans = dp[n][n] + 2 * 400 * sum + n * 10;
}

void p()
{
    printf("%d\n", ans);
}

int main()
{

    int t;
    scanf("%d",&t);
    while(t--)
    {
        read();
        init( n );
        dpsolve();
        p();
    }
    return 0;
}




下面是另一份

#include 
#include 
using namespace std;

#define MAX 1010
#define INF 1000000000


int n, i, j, k, sum, ans;
int x[MAX], dis[MAX][MAX] ,dp[MAX][MAX];

inline int min(int a, int b)
{
	return a < b ? a : b;
}

void read()
{

	scanf("%d",&n);
	x[0] = 0;
	for(i = 1; i <= n; i++ )
	{
		scanf("%d%d",&sum, &x[i]);
	}
	for(i = 0; i <= n; i++ )
	{
		for(j = 0; j <= n; j++ )
		{
			dis[i][j] = min( abs( x[i] - x[j]), 360 - ( abs( x[i] - x[j] ) ) );
		}
	}


}

void init( int n )
{
	for(i = 0; i <= n; i++ )
	{
		for(j = 0; j <= n; j++)
		{
			dp[i][j] = INF;
		}
	}
}

void dpsolve()
{
	
	dp[0][0] = 0;
	for(i = 1; i <= n; i++)
	{
		for(j = 0; j <= i; j++)
		{
			if(i == 1 && j == 0 ) {dp[i][j] = dis[i][j];continue;} //否则这里会出现dp[1][0] = mix(dp[1][0], dp[0][0] + dis[1][0]),答案出现错误
			if( j < i - 1 ) dp[i][j] = dp[ i - 1 ][j] + dis[ i - 1 ][i];
		/*
			else if(j == i - 1)
			{
				for(k = 0; k <= j; k++)
				{
					dp[i][j] = min( dp[i][j], dp[j][k] + dis[k][i]);
				}
			}
			*/
			else 
			{
				for(k = 0; k <= j; k++)
				{
					dp[i][j] = min( dp[i][j], dp[j][k] + dis[k][i] );
				}
			}
		}
	}
	ans = dp[n][n] + 2 * 400 * sum + n * 10;
}

void p()
{
	printf("%d\n", ans);
}

int main()
{

	int t;
	scanf("%d",&t);
	while(t--)
	{
		read();
		init( n );
		dpsolve();
		p();
	}
	return 0;
}


你可能感兴趣的:(百度之星1002)