Блог пользователя question_id

Автор question_id, 12 лет назад, По-английски

Here is a problem I had been trying in Light Oj.

Problem link: http://paste.ubuntu.com/11060539/ (Since Light OJ need a user id to access)

I could solve it recursively: My solution: http://paste.ubuntu.com/11060583/

Now I want to solve it iteratively. But I am failing to do it. Please explain me how I can do this in iterative process in two dimension array like, int dp[102][10002]:: dp[n][k];

In some code I see to act like this: for(int i=0;i<=n;i++) dp[i][0]=1;

why does it fill,fill dp[i][0]?

Please I need to learn this . I am trying but failing.

Thanks in advance.

  • Проголосовать: нравится
  • +1
  • Проголосовать: не нравится

»
12 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

The point of iterative solution is to create a state dp[current coin][current sum]. So we do the "for(int i = 0; i <= N; i++) dp[i][0]=1;" because we can make sum=0 using first i coins only 1 way (by not picking any). Then the dp[i][k] (let i be the current coin's number and k be the current sum) will be the sum of dp[i-1][k-a[i]*x] for every x such that k-a[i]*x >= 0. But even in this case the solution could get TL. As you see we calculate some things many times ( The operations to update the current states are O(K) ). We can get them just to O(1) by creating a prefix array witch is completed like that: pref[i][k] = dp[i][k] + pref[i][k-a[i]]. And then dp[i][k] = pref[i-1][k]. So at the end the time complexity will be O(N*K*T), witch will fit in TL.

»
12 лет назад, скрыть # |
 
Проголосовать: нравится +5 Проголосовать: не нравится

your recurrance is like: dp (i,j) = dp(i,j)+ dp(i+1, j—some_value) . So u can see that, value of state (i,j) depends on values of some state which are of the form ( m , k) where m=i+1 and k is less than j.

While doing iterative dp, u need to pay attention to the order in which you need the values. Here before computing state dp[i][j], you need values of dp[i+1][j-something].

You need two nested loops. If you put iteration over i in outer loop, you need to iterate from higher value of i to lower value of i, because to calculate dp[i][j], you need dp[i+1][j-something]. And if you you put iteration over j in outer loop, you need to iterate from lower value of j to higher value of j.

If you put j in outer loop, to calculate dp[i][j] you need dp[i+1][j-something], so u need values of states with lower values of j. the lowest value of j is 0, dp[i][0]=1 for all i, and dp[n+1][j] is zero for all j except 0. this is your base case. so u can do it in following way

for(int i=1;i<=n+1;i++) dp[i][0]=1; //base case
for(int j=1;j<=K;j++) dp[n+1][j]=0; //base case

for(int j=1;j<=K;j++) // j should iterate from low to high
{
  for(int i=1;i<=n;i++) // order of iteration on i does not matter here
  {
      // your calculation
      dp[i][j]=0
      for(.....)
      {
          dp[i][j]  =(dp[i][j] + dp[i+1][j- something] ) %mod;
      }

  }
}

If you put i in outer loop, to calculate dp[i][j] you need dp[i+1][j-something], so u need values of states with higher value of i. the highest value of i is n+1. so u can dot it in the following way also,

for(int i=1;i<=n+1;i++) dp[i][0]=1; //base case
for(int j=1;j<=K;j++) dp[n+1][j]=0; //base case

for(int i=n;i>=1;i--) // i should iterate from high to low
{
  for(int j=1;i<=n;i++) // order of iteration on j does not matter here
  {
     // your calculation
      dp[i][j]=0
      for(.....)
      {
          dp[i][j]  =(dp[i][j] + dp[i+1][j- something] ) %mod;
      }
  }
}

In other problems, you need to decide how to iterate over the value (from lower to higher or from higher to lower) from your recurrence. In some problems, putting one of the variables in outer loop may be more convenient than the other. You will learn from experience.