class Solution {
public int coinChange(int[] coins, int amount) {
int n = coins.length;
int ans = tabOpt(coins,amount,n);
if(ans >=(int)Math.pow(10,9)) return -1;
return ans;
}
int tabOpt(int[] c, int am, int n){
int[] dp = new int[am+1];
for(int i=1;i<=am;i++) dp[i] = (i%c[0]==0)?i/c[0]: (int)Math.pow(10,9);
for(int i=1;i<n;i++){
int[] cur = new int[am +1];
for(int j=1;j<=am;j++){
int tk = (j-c[i]>=0)? (1+cur[j-c[i]]):(int)Math.pow(10,9);
int ntk = dp[j];
cur[j] = Math.min(tk,ntk);
}
dp=cur;
}
return dp[am];
}
int tab(int[] c, int am, int n){
int[][] dp = new int[n][am+1];
for(int i=1;i<=am;i++) dp[0][i] = (i%c[0]==0)?i/c[0]: (int)Math.pow(10,9);
for(int i=1;i<n;i++){
for(int j=1;j<=am;j++){
int tk = (j-c[i]>=0)? (1+dp[i][j-c[i]]):(int)Math.pow(10,9);
int ntk = dp[i-1][j];
dp[i][j] = Math.min(tk,ntk);
}
}
return dp[n-1][am];
}
int func(int i, int am, int[] c, int[][] dp){
if(am<0) return (int)Math.pow(10,9);
if(am==0) return 0;
if(i==0) return dp[i][am] = (am%c[i]==0)?am/c[i]:(int)Math.pow(10,9);
if(dp[i][am]!=-1) return dp[i][am];
int tk = 1 + func(i, am-c[i], c,dp);
int ntk = func(i-1,am,c,dp);
return dp[i][am] = Math.min(tk,ntk);
}
}