using System.Collections.Generic;
private static int TargetSum(int[] nums, int T, int i, Dictionary<Tuple<int,int>, int> cache){
var targetPositionPair = new Tuple<int,int>(T,i);
if (cache.ContainsKey(targetPositionPair)){
return cache[targetPositionPair];
var waysAfterAdding = TargetSum(nums, T - nums[i], i + 1, cache);
var waysAfterSubtracting = TargetSum(nums, T + nums[i], i + 1, cache);
var totalWays = waysAfterAdding + waysAfterSubtracting;
cache.Add(targetPositionPair, totalWays);
public static int TargetSum(int[] nums, int T){
var cache = new Dictionary<Tuple<int,int>, int>();
return TargetSum(nums, T, 0, cache);
private static int TargetSum2(int[] nums, int T){
foreach(var num in nums){
maxNumsSum += Math.Abs(num);
minNumsSum -= Math.Abs(num);
if (maxNumsSum == 0) return 0;
var cache = new int[(2*maxNumsSum)+1, nums.Length+1];
for(var i=1; i<cache.GetLength(1); i++){
for(var t=0; t<cache.GetLength(0); t++){
if (t-nums[i-1]+offset >= 0 && t-nums[i-1]+offset < (2*maxNumsSum)+1){
ways += cache[t-nums[i-1]+offset,i-1];
if (t+nums[i-1]+offset >= 0 && t+nums[i-1]+offset < (2*maxNumsSum)+1){
ways += cache[t+nums[i-1]+offset,i-1];
if (t+offset >= 0 && t+offset < (2*maxNumsSum)+1){
var wantedIndexedT = T+offset;
return cache[wantedIndexedT, nums.Length];
public static void Main()
var nums = new int[]{1,1,2,3};
Console.WriteLine(TargetSum(nums,T));
Console.WriteLine(TargetSum2(nums,T));