荣誉版主
- 积分
- -2403
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2010-5-4
- 最后登录
- 1970-1-1
|
回复 wwwyhx
有点类似,对于f[ i][j],也就是把前i个数弄成递减,且最后一个数是j的最小代价可能由两种途径达到。对于所有可能的k >= j,有
f[ i][j] = min_k{ min{ f[k] + g(a[ i],j), f[j] + a } }
分别是把前i-1个数弄成递减且最后一个数是k的代价加上把第i个数弄成j的代价,和把前i-1个数弄成递减且最后一个数是j的代价加上把第i个数删掉的代价。这里g(a,j)就是把a弄成j需要的代价。
g(a,b)=(a>=b?(a-b):INFINITY)
darksteel 发表于 2011-6-15 11:03 ![]()
大致看了一下,这题一个关键就是可以删除数字,写了一个O(n^4)的解法,不知道是不是可以简化,还有那个ACM题因该是O(n^3)而非O(n^2)
//Cost(i,j) = min(Cost(i-1,j), Cost(i-2,j)+a[i-1], Cost(i-3,j)+a[i-2])
int CalcCost(int a[], int n)
{
int nMaxCost = 0;
int* arrSorted = new int[n];
for (int i = 0; i < n; i++)
{
if (a[i] <= 0) return -1;
nMaxCost += a[i];
arrSorted[i] = a[i];
}
sort(arrSorted, arrSorted+n);
int** pDP = new int*[n];
for (int i = 0; i < n; i++)
pDP[i] = new int[n];
//initialize
for (int i = 0; i < n; i++)
pDP[0][i] = a[0] - arrSorted[i];
for (int i = 1; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (arrSorted[j] > a[i])
pDP[i][j] = a[i] - arrSorted[j];
else
{
int nMinCost = nMaxCost;
int nCostSum = a[i] - arrSorted[j];
for (int k = i-1; k >= 0; k--)
{
for (int x = j; x < n; x++)
{
if (pDP[k][x] >= 0)
{
if (nCostSum + pDP[k][x] < nMinCost)
nMinCost = nCostSum + pDP[k][x];
}
}
nCostSum += a[k];
}
nMinCost = nMinCost < nCostSum ? nMinCost : nCostSum;
pDP[i][j] = nMinCost;
}
}
}
//get minimum costs
int nMinCost = nMaxCost;
for (int i = 0; i < n; i++)
{
if (pDP[n-1][i] < 0) continue;
nMinCost = nMinCost < pDP[n-1][i] ? nMinCost : pDP[n-1][i];
}
int nSumCost = a[n-1];
for (int i = n-2; i >= 0; i--)
{
for (int j = 0; j < n; j++)
{
if (pDP[i][j] >= 0)
nMinCost = nMinCost < pDP[i][j]+nSumCost ? nMinCost : pDP[i][j]+nSumCost;
nSumCost += a[i];
}
}
for (int i = 0; i < n; i++)
delete []pDP[i];
delete []pDP;
delete []arrSorted;
return nMinCost;
} |
|