1. 程式人生 > >動態規劃與分治學習總結

動態規劃與分治學習總結

  • 6.1 二分查詢
二分查詢半開區間, 左閉右開 例如:[1,5) [5,10)
package 分治與動態規劃;

public class 二分查詢
{
	public static void main(String[] args)
	{
		int[] arr = { 1, 2, 3, 4, 5 };
		System.out.println(f(arr, 5));
	}

	private static int f(int[] arr, int i)
	{
		if (i > arr.length)
		{
			return -1;
		}
		return f(arr, i, 0, arr.length);
	}

	/**
	 * 
	 * @param arr
	 * @param find
	 *            要找的
	 * @param begin
	 *            左閉
	 * @param end
	 *            右開
	 */
	private static int f(int[] arr, int find, int begin, int end)
	{
		if (end - begin == 1)
		{
			if (find != arr[begin])
			{
				return -1;
			}
			return begin;
		}
		int hi = (begin + end) / 2;
		if (arr[hi] > find)
		{
			return f(arr, find, begin, hi);
		} else if ((arr[hi] < find))
		{
			return f(arr, find, hi, end);
		}
		return hi;
	}
}


  • 6.2 最大連續部分和
最大連續部分和陣列中整數有正有負求連續一子段,使得和最大化2,4,-7,5,2,-1,2,-4,3最大連續段:5,2,-1,2最大和為8
package 分治與動態規劃;

public class 分治最大連續部分和
{

	public static void main(String[] args)
	{
		int[] arr = { 2, 4, -7, 5, 2, -1, 2, -4, 3 };
		System.out.println(f(arr, 0, arr.length));
	}

	private static int f(int[] arr, int begin, int end)
	{
		if (end - begin == 1)
		{
			if (arr[begin] > 0)
			{
				return arr[begin];
			}
			return 0;
		}
		int k = (begin + end) / 2;
		int left = f(arr, begin, k);
		int right = f(arr, k, end);

		int leftk = 0;
		int sum = 0;
		// 向左擴充套件
		for (int i = k - 1; i >= begin; i--)
		{
			sum += arr[i];
			if (sum >= leftk)
			{
				leftk = sum;
			}
		}

		int rightk = 0;
		sum=0;
		// 向左擴充套件
		for (int i = k; i < end; i++)
		{
			sum += arr[i];
			if (sum >= rightk)
			{
				rightk = sum;
			}
		}
		
		int kz=leftk+rightk;
		return Math.max(kz, Math.max(right, left));
	}

}

  • 6.3快取結果
快取結果比如斐波拉契數列f(9) = f(8) + f(7)=(f(7)+f(6)) + (f(6)+f(5))=((f(6)+f(5))+(f(5)+f(4))) + ((f(5)+f(4))+(f(4)+f(3)))= ....同樣引數的函式算了很多遍解決方法:1快取(按需存放)2仔細設計計算次序,可以用陣列
package 分治與動態規劃;

import java.util.HashMap;
import java.util.Map;

public class 取球博弈程式碼用快取
{

	static private Map<Integer, Boolean> result=new HashMap<>();
	public static void main(String[] args)
	{
		int i=1055;
		System.out.println(i+" "+f(i));
	}

	private static boolean f(int i)
	{
		if (i==0)
		{//最後一個球被對方取走了,那我就贏了
			return true;
		}
		if (result.get(i)!=null)
		{
			return result.get(i);
		}
		try
		{
			if (i>=1&&f(i-1)==false)return true;
			if (i>=3&&f(i-3)==false)return true;
			if (i>=7&&f(i-7)==false)return true;
			if (i>=8&&f(i-8)==false)return true;					
		} finally
		{
			result.put(i, true);
		}
		result.put(i, false);
		return false;
	}
}

  • 6..4動態規劃
動態規劃城牆頂刷漆 X國的一段古城牆的頂端可以看成 2*N個格子組成的矩形(如圖所示)現需要把這些格子刷上保護漆。你可以從任意一個格子刷起,刷完一格,可以移動到和它相鄰的格子(對角相鄰也算數),但不能移動到較遠的格子(因為油漆未乾不能踩!)比如:a d b c e f 就是合格的刷漆順序。c e f d a b 是另一種合適的方案。當已知 N 時,求總的方案數。當N較大時,結果會迅速增大,請把結果對 1000000007 (十億零七) 取模。輸入資料為一個正整數(不大於1000)輸出資料為一個正整數。例如:使用者輸入:2程式應該輸出:24再例如:使用者輸入:3程式應該輸出:96再例如:使用者輸入:22程式應該輸出:359635897
錦囊1fb(n) 從某個邊緣格子,到與它對面的格子結束,fb(n) = fb(n-1) * 2 錦囊2:fa(n) 從某個邊緣格子開始的所有情況(再晚走這格就來不及了)fa(n) = fb(n) 最後走對面格+2*fa(n-1) 第1步走對面格+4*fa(n-2) 第2步走對面格
package 分治與動態規劃;

public class 城牆頂刷漆
{
	static final long M = 1000000007;

	public static long fb(int n)
	{
		if (n == 1)
		{
			return 1;
		}
		return fb(n - 1) % M * 2 % M;
	}

	public static long fa(int n)
	{
		if (n == 1)
		{
			return 1;
		}
		if (n == 2)
		{
			return 6;
		}
		return (fb(n) % M + 2 * fa(n - 1) % M + 4 * fa(n - 2) % M) % M;
	}

	public static long fk(int i, int n)
	{
		return ((fb(i) % M * fa(n - i) % M) % M * 2 % M + (fb(n - i + 1) % M * fa(i - 1) % M) % M * 2 % M) % M * 2 % M;
	}

	public static long f(int n)
	{
		if (n == 1)
		{
			return 2;
		}
		long sum = fa(n) * 4 % M;
		for (int i = 2; i < n; i++)
		{
			sum = (sum % M + fk(i, n) % M) % M;
		}
		return sum % M;
	}

	public static void main(String[] args)
	{
		for (int i = 1; i < 30; i++)
		{
			System.out.println(i + " " + f(i));
		}
	}

}

  • 6..5作業
作業 環形塗色如圖,組成環形的格子需要塗3種顏色。它們的編號分別是1~14相鄰的格子不能用相同的顏色。塗色方案的數目是:24576當格子數目為50的時候,求塗色方案總數。
package 分治與動態規劃;


public class 環形塗色
{
	static final int BlUE=1;
	static final int RED=2;
	static final int YELLOW=3;
	static int count;
	public static void main(String[] args)
	{
		int colorArrays[]=new int[14];
		dfs(0,colorArrays);
		System.out.println(count);
	}
	private static void dfs(int i, int[] colorArrays)
	{
		if (i==colorArrays.length)
		{
			if (check(colorArrays)==true)
			{
				count++;
//				System.out.println(Arrays.toString(colorArrays));
			}
			return;
		}
		for (int j = BlUE; j <= YELLOW; j++)
		{
			int old=colorArrays[i];
			colorArrays[i]=j;
			
			dfs(i+1, colorArrays);
			
			colorArrays[i]=old;
		}
		
	}
	private static boolean check(int[] colorArrays)
	{
		for (int i = 1; i < colorArrays.length-1; i++)
		{
			if (colorArrays[i]==colorArrays[i+1]||colorArrays[i]==colorArrays[i-1])
			{
				return false;
			}
		}
		if (colorArrays[0]==colorArrays[colorArrays.length-1])
		{
			return false;
		}
		return true;
	}

}