您的位置:首页 > 其它

UVA 10003 - Cutting Sticks

2015-03-16 14:03 288 查看
最优矩阵链乘问题:状态转移方程如下:(比较繁琐,稍后会有优化版)

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: