ACM PKU 1160 Post Office http://acm.pku.edu.cn/JudgeOnline/problem?id=1160
来之不易呀!!!
用opt[i][j]记录把前i个邮局建到前j个村庄中的最优解
用cost[i][j]记录所有在i到j村庄中,建1个邮局的最小代价。显然邮局应该设到中点。
让前i个邮局覆盖前j个村庄,第i+1个邮局覆盖第j+1至j+k个村庄(j+k<=n),则状态转移方程为
opt[i+1][j+k]=min{opt[i][j]+cost[j+1][j+k];} (k+j<=n)
#include <iostream>
using namespace std;
const int MAX = 3000000;
long cost[301][301];
long opt[301][301];
int dis[301];
int main ()
{
int v, p_o ;
int i = 1, j , k ;
//memset (cost,0,sizeof(cost));
cin >> v >> p_o;
for (i = 1; i <= v; i++ )
cin >> dis[i];
for (i = 1 ; i <= v ; i++)
for (j = i; j <= v ; j++)
{
cost[i][j] = 0;
int mid = (i + j)/2;
for (k = mid + 1; k <= j; k++)
{
cost[i][j] += dis[k] - dis[mid] ;
}
for (k = i ; k <= mid ; k++)
{
cost[i][j] += dis[mid] - dis[k] ;
}
}
for (i = 0 ; i <= p_o; i++)
for (j = 0; j <= v ; j++)
{
opt[i][j] = MAX;
}
重点看看这里:
opt[0][0] = 0;
for (i = 0 ; i <= p_o; i++)
for (j = 0; j <= v ; j++)
{
for (k = 1; k + j <= v; k++)
if ( opt[i+1][j+k] > opt[i][j] + cost[j+1][j+k])
{
opt[i+1][j+k] = opt[i][j] + cost[j+1][j+k];
}
}
cout<<opt[p_o][v]<<endl;
return 0;
}
浙公网安备 33010602011771号