UVA 10003 - Cutting Sticks

最优矩阵链乘问题:状态转移方程如下:(比较繁琐,稍后会有优化版)

f[i][j] = f[i][k] + f[k][j] + a[j] - [i];//a[]存储切点i,j代表线段的头和尾

利用递推运算,先把线段之间没有切点的收费情况即f[i][j]赋值为零,然后利用这个推出线段之间只有一个切点的线段,如此不断扩大,当线段的头尾一个是0一个是给出的长度,也就AC了:

代码如下:(此代码不理想,浪费空间,但可AC)

#include<stdio.h>
#include<string.h>
#define INF 0x7fffffff
#define MAXN 1000 + 10
int L, num, a[55], f[MAXN][MAXN];
void solve()
{
//for(int i = 0; i < MAXN; i ++)
// for(int j = 0; j < MAXN; j ++)
// f[i][j] = 1100;
for(int i = 0; i <= num ; i ++)
f[a[i]][a[i+1]] = 0;
for(int j = 2;j <= num + 1 ;j ++)
for(int i = 0; i+j <= num+1; i ++)
{
f[a[i]][a[i+j]] = INF;
for(int k = i+1; k < i +j; k ++)
if(k>i)
{
if(f[a[i]][a[i + j]]>(f[a[i]][a[k]]+f[a[k]][a[i+j]]+a[i+j]-a[i]))
f[a[i]][a[i + j]] = f[a[i]][a[k]]+f[a[k]][a[i+j]]+a[i+j]-a[i];
}
}
printf("The minimum cutting is %d.\n",f[0][L]);
}
void input()
{
while(scanf("%d",&L) == 1)
{
if(L == 0) break;
scanf("%d",&num);
a[0] = 0;
for(int i = 1; i <= num; i ++)
scanf("%d",&a[i]);
a[num+1] = L;
solve();
}
}
int main()
{
input();
return 0;
}

这个代码好一点:(0.172s)

#include<stdio.h>
#include<string.h>
#define INF 0x7fffffff
#define MAXN 60
int L, num, a[55], f[MAXN][MAXN];
void solve()
{
for(int i = 0; i <= num ; i ++)
f[i][i+1] = 0;
for(int j = 2;j <= num + 1 ;j ++)
for(int i = 0; i+j <= num+1; i ++)
{
f[i][i+j] = INF;
for(int k = i+1; k < i +j; k ++)
if(k>i)
{
if(f[i][i + j]>(f[i][k]+f[k][i+j]+a[i+j] - a[i]))
f[i][i + j] = f[i][k] + f[k][i+j] + a[i+j] - a[i];
}
}
printf("The minimum cutting is %d.\n",f[0][num+1]);
}
void input()
{
while(scanf("%d",&L) == 1)
{
if(L == 0) break;
scanf("%d",&num);
a[0] = 0;
for(int i = 1; i <= num; i ++)
scanf("%d",&a[i]);
a[num+1] = L;
solve();
}
}
int main()
{
input();
return 0;
}




posted on 2012-03-10 22:32  BFP  阅读(568)  评论(0编辑  收藏  举报