Page **1** of **4**

### 10003 - Cutting Sticks

Posted: **Sat Oct 19, 2002 9:52 pm**

by **otavio**

I have written a program for the 10003 problem, but Jugde tells me that it uses more time than allowed.

I can't understand, because I have generated a long test set (over 160 entries with 50 cutting points each) and my program runs for less than 1 second in a Pentium 200.

What's wrong?

Ot

Posted: **Sun Nov 10, 2002 8:06 am**

by **Mahbub**

Hi,

Did u notice that this is a simple example of "Matrix Chain Mutiplcation" dp

algorithm? In case u have used that and still getting TLE...u may find this

code helpful

Code: Select all

```
#include<stdio.h>
#include<values.h>
#define MAX 60
#define inf MAXLONG
int main()
{
long L,N,i,j,n,x,y,q,l,k,t,sum,m[MAX][MAX],p[MAX];
while(scanf("%ld",&L)==1 && L)
{
scanf("%ld",&N);
y = 0;
for(i=1;i<=N;i++)
{
scanf("%ld",&x);
p[i] = x - y;
y = x;
}
p[i] = L - y;
n = i;
for(i=0;i<=n;i++)
m[i][i] = 0;
for(l=2;l<=n;l++)
{
for(i=1;i<=n-l+1;i++)
{
j = i + l - 1;
m[i][j] = inf;
for(k=i;k<=j-1;k++)
{
q = m[i][k] + m[k+1][j] ;
sum = 0;
for(t=i;t<=j;t++)
sum += p[t];
q += sum;
if(q<m[i][j])
m[i][j] = q;
}
}
}
printf("The minimum cutting is %ld.\n",m[1][n]);
}
return 0;
}
```

### 10003

Posted: **Wed Dec 25, 2002 7:35 am**

by **ec3_limz**

How do I solve #10003: Cutting Sticks using Dynamic Programming (DP)? I have seen others' source code, but I don't understand how and why they work.

Please tell me.

DP is so complicated

Posted: **Wed Dec 25, 2002 6:13 pm**

by **Larry**

It's a similar problem to matrix multiplication, so if you're familiar with that DP (which is in most intro texts) problem, then maybe you can think that way.

### 10003 (after New Judgement)

Posted: **Mon Jan 20, 2003 2:51 pm**

by **hank**

after

New Judgement I got wrong answer.

but I don't know why.

Anyone can help me?

[c]#include "stdio.h"

int dim[50],cost[50][50],cut;

int Min(int a,int b)

{

if(a>b) return b;

return a;

}

void clear_var()

{

int i,j;

for(i=0;i<=cut;i++)

for(j=0;j<=cut;j++)

cost

*[j]=0;*

for(i=0;i<50;i++)

dim*=0;*

}

void DP()

{

int i,j,k;

for( j=2 ; j<=cut; j++)

{

for(i=cut ; i>=0 ; i--)

{

for(k= i+1 ; k<=cut ; k++ )

{

if( i<k && i<j && k<j )

{

if( k==i+1 ){

cost*[j]= cost**[k] + cost[k][j] +dim[j]-dim**;*

}else{

cost*[j]= Min(cost**[j],cost**[k]+cost[k][j]+dim[j]-dim**);*

}

}

}

}

}

}

void main()

{

int len,i,j;

while( scanf("%d",&len) == 1)

{

if(len==0) break;

clear_var();

scanf("%d",&cut);

cut++;

dim[0]=0;

for(i=1;i<cut;i++)

scanf("%d",&dim*);*

dim[cut]=len;

DP();

printf("The minimum cutting is %d.\n",cost[0][cut]);

}

}

[/c]

Posted: **Tue Jan 21, 2003 11:29 am**

by **Astrakan**

Try this case:

Code: Select all

```
1000
49
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
```

Output should be 1279.

Posted: **Thu Jan 30, 2003 10:48 am**

by **hank**

I can't understand what the problem said.

Anybody can tell me?

### Re: How to solve #10003: Cutting Sticks using DP?

Posted: **Thu Jan 30, 2003 12:21 pm**

by **turuthok**

ec3_limz wrote:How do I solve #10003: Cutting Sticks using Dynamic Programming (DP)? I have seen others' source code, but I don't understand how and why they work.

Please tell me.

DP is so complicated

DP is so interesting ... whoever came up with it was a genius. It might be complicated at first, but once you get used to it, you're gonna love it.

The main idea for this problem is that we can try to solve the min-cost for lowest range of cut-points, and then expand our range one by one until you got the cost for the maximum range.

Let's say you have cut-points a, b, c (strictly increasing position) of a stick whose length is x. Then what I meant by cost of lowest range would be the cost to cut 0..a, a..b, b..c, and c..x. Once you got the cost for all 4 of them, you proceed with calculating wider range ... in this case, the next range would be 0..b, a..c, b..x ... Calculating min-cost for these ranges are easy since you already got the min-cost for smaller ranges ...

I don't want to take away all your fun, so we should stop here ...

-turuthok-

### 10003 (Cutting Sticks) WA I/O

Posted: **Thu Jul 31, 2003 11:27 pm**

by **UFP2161**

Could someone give me correct output for the following randomly generated input? Thanks in advance!

970

7

108 167 225 275 411 651 824

111

10

10 17 28 30 37 44 47 49 77 94

318

17

19 33 40 48 63 77 89 92 101 121 149 150 162 174 197 198 261

830

11

32 69 104 170 208 219 327 420 552 582 799

311

10

22 29 56 89 110 129 158 161 217 291

578

6

50 128 148 274 408 542

871

17

21 31 66 105 129 159 168 210 257 261 312 402 446 465 544 615 653

730

2

273 426

456

4

2 17 112 375

355

5

61 67 161 183 194

0

Posted: **Sat Aug 09, 2003 8:22 am**

by **Larry**

Code: Select all

```
The minimum cutting is 2778.
The minimum cutting is 348.
The minimum cutting is 1203.
The minimum cutting is 2827.
The minimum cutting is 1034.
The minimum cutting is 1572.
The minimum cutting is 3271.
The minimum cutting is 1156.
The minimum cutting is 929.
The minimum cutting is 776.
```

### Re: How to solve #10003: Cutting Sticks using DP?

Posted: **Sat Nov 01, 2003 3:50 am**

by **Algoritmo**

ec3_limz wrote:How do I solve #10003: Cutting Sticks using Dynamic Programming (DP)? I have seen others' source code, but I don't understand how and why they work.

Please tell me.

DP is so complicated

ec3_limz, have a look at this tutorial:

http://mat.gsia.cmu.edu/classes/dynamic/dynamic.html
From example 2 of this tutorial I introduced myself into what is DP. In problem 10003 I practiced it by the first time.

My first solution was made by backtracking, with this simple recursive definition:

Code: Select all

```
MinCost (Stick):
if there are no cuts, Min Cost = 0;
else:
for each cut n
Cost of n = Min Cost (Stick at left of n) + Min Cost (Stick at right of n)
Min Cost = Smallest Cost
```

In C++, the program is just a bit bigger than this definition. This program was capable of giving any answer, but it was too costy and got Time Limit Exceeded.

On my first DP solution, I made 1 cut at each stage and each stage did only depend on the information computed in previous stage. It was a VERY complex program, which took me many hours. It also worked, but also got Time Limit Exceeded.

Then I followed what turuthok said, defining stage N as the calculation of sticks with length N. Each stage now depends on ALL previously computed ones. With a simple drawing I perceived that is the correct way to do the DP. Memory allocation requirements were now much lower and my program was finally Accepted, in 1 sec.

Posted: **Mon Nov 03, 2003 9:36 am**

by **bnbolo**

- The minimum cutting is 2778.

The minimum cutting is 351.

The minimum cutting is 1209.

The minimum cutting is 2974.

The minimum cutting is 1068.

The minimum cutting is 1662.

The minimum cutting is 3345.

The minimum cutting is 1156.

The minimum cutting is 929.

The minimum cutting is 776.

**I don't know where is wrong.**

Posted: **Fri Nov 07, 2003 8:22 am**

by **ColdAndUgly**

I got the same output as bnbolo did.

Here is my code, if someone could make a suggestion, i would appreciate it.

[cpp]

// 10003 - Cutting Sticks.cpp : Defines the entry point for the console application.

//

#include <stdio.h>

#include <stdlib.h>

int iCutList[60][2];

int iWorkingArray[60];

void main()

{

int iTerm = 0;

int iLength;

int iCuts;

int iCut;

int iLoop1;

int iLoop2;

int iSum;

int iTotal;

int iPlaceHolder;

while(iTerm != 1) {

scanf("\n%d", &iLength);

if(iLength == 0)

iTerm = 1;

else {

scanf("\n%d", &iCuts);

scanf("\n%d", &iCut);

iCutList[0] [0] = 0;

iCutList[0] [1] = iCut;

iWorkingArray[0] = iCut;

for(iLoop1 = 1; iLoop1 < iCuts; iLoop1++){

scanf(" %d", &iCut);

iCutList[iLoop1] [0] = iCutList[iLoop1 - 1] [1];

iCutList[iLoop1] [1] = iCut;

iWorkingArray[iLoop1] = iCutList[iLoop1] [1] - iCutList[iLoop1] [0];

}

iWorkingArray[iLoop1] = iLength - iCutList[iLoop1 - 1] [1];

fflush(stdin);

iTotal = 0;

for(iLoop1 = iCuts; iLoop1 > 0; iLoop1--) {

//scanf all the values to find the smallest combination

iSum = 2000;

for(iLoop2 = 0; iLoop2 < iLoop1; iLoop2++) {

if(iWorkingArray[iLoop2] + iWorkingArray[iLoop2 + 1] <= iSum) {

iSum = iWorkingArray[iLoop2] + iWorkingArray[iLoop2 + 1];

iPlaceHolder = iLoop2;

}

}

//smallest found, now add to total, and combine pieces

iTotal = iTotal + iSum;

iWorkingArray[iPlaceHolder] = iSum;

for(iLoop2 = iPlaceHolder + 1; iLoop2 < iLoop1; iLoop2++) {

iWorkingArray[iLoop2] = iWorkingArray[iLoop2 + 1];

}

iWorkingArray[iLoop2] = 0;

}

printf("The minimum cutting is %d.\n", iTotal);

}

}

}

[/cpp]

thanks,

chris

Posted: **Fri Nov 07, 2003 8:26 am**

by **ColdAndUgly**

I followed the method above to code this program, and i got a WA. Another thread contains some sample input, and a lot of my input didn't match. If anyone can take a look at it, i would appreciate it.

http://online-judge.uva.es/board/viewto ... ight=10003
thanks,

chris

Posted: **Sat Nov 08, 2003 11:21 am**

by **Algoritmo**

ColdAndUgly wrote:I got the same output as bnbolo did.

Here is my code, if someone could make a suggestion, i would appreciate it.

[cpp]

...

[/cpp]

thanks,

chris

In first place, I would like to sujest some changes in your code (and maybe in your way of coding). They make the code easyer to understand and find possible mistakes.

1:

The array iCutList[60][2] represents the cost and the length of 60 possible sticks, right? So it should be separated in Cost[60] and Length[60], as you will never use a variable in the second array dimension (example: iCutList[30][n]). If you prefer, you can make a struct (Stick[n].Cost and Stick[n].Length).

2:

I dont think you need fflush(stdin) and you don't need the "\n" or space in scanf format string unless you are using "%c" or gets() function.

3:

Instead of using an enormous else block, you could use:

Code: Select all

```
while (1) {
if (iLength == 0) break;
block....
}
```

Or even better:

Code: Select all

```
while (scanf("\n%d", &iLength)==1 && iLength) {
block....
}
```

4:

Reading the code, I discovered you simply dont make use of the iCutList array in processing part. You use the iWorkingArray array instead. So iCutList is not beeing usefull there.

Well, I did not entirelly understand your code, but I see the array iWorkingArray get's smaller at each node of DP. This is not what I did. Node N calculates length and accumulated price for sticks that join N-1 final parts.... So a stick of N parts can result from:

stick with N-1 parts + Stick with 1 parts

stick with N-2 parts + Stick with 2 parts

stick with N-3 parts + Stick with 3 parts

...

So in my case, at each stage of DP more sticks are calculated and no stick is forgoten...

Hope I have helped.