Problem 1005
问题:一堆石头划分问题,将一堆石头划分成两堆,使这两堆石头之间的重量差最小。
输入:第一行---石头的总数量(1~20)
第二行---各石头的重量,之间用空格间隔(每个石头重量在1~100000)
输出:两堆石头最小的重量差。
实现代码:
using System; namespace Q1005 { class Program { static void Main(string[] args) { int num = Int16.Parse(Console.ReadLine()); int[] array = new int[num]; string[] str = Console.ReadLine().Split(); for (int i = 0; i < num; i++) array[i] = Int32.Parse(str[i]); int min = MinDifferent(array); Console.WriteLine("{0}", min); } //0-1背包方法 static int MinDifferent(int[] array) { int sum=0; for (int i = 0; i < array.Length; i++) sum += array[i]; int[] dp = new int[sum+1]; //背包问题,此背包能够容纳全部的值,且物品的价值等于物品的大小 //且dp[k]记录的是背包容量为k时的最大值 for (int i = 0; i < array.Length; i++) for (int k = sum; k >= array[i]; k--) dp[k] = Math.Max(dp[k], dp[k - array[i]] + array[i]); int min = Int32.MaxValue; //找出其中容量为k时的最大值使之与sum/2最接近 for (int i = 0; i <= sum; i++) if (Math.Abs(sum/2 - dp[i]) < min) min = Math.Abs(sum / 2 - dp[i]); return (min*2+sum%2); } } }
主要知识点:
此问题的暴力解法,参见:比较灵活的暴力法,利用移位http://www.cnblogs.com/skyivben/archive/2008/07/26/1251907.html
或利用每个石头之间总共有的+,-情况:
http://blog.163.com/yinson_lin/blog/static/22120172008112552832626/
Problem 1009
问题:N位的K进制数个数,其中此K进制数个数有一定的限制条件:
1. 两个位之间包含两个0及以上0的不属于,如 10010不属于5进制数。
2. 最高位不允许为0,如011不属于3进制数。
输入:第一行---N(位数---取N>=2)
第二行---K(进制---取2<=K<=10)
且要求N+K<=18
输出:符合要求的K进制数总个数
实现代码:
using System; namespace Q1009 { class Program { static void Main(string[] args) { int n = Int16.Parse(Console.ReadLine()); int k = Int16.Parse(Console.ReadLine()); Console.WriteLine(DPTotal(k, n)); Console.WriteLine(TotalNum(k, n)); Console.ReadKey(); } static int TotalNum(int k, int n) { int[] store = new int[n + 1]; //1位数和2位数的情况 store[1] = k - 1; store[2] = (k - 1) * k; //采用归纳法得出的结论 for (int i = 3; i <=n; i++) store[i] = (k - 1) * (store[i - 1] + store[i - 2]); return store[n]; } } }
主要知识点:
- 在于获取表达式 store[i] = (k - 1) * (store[i - 1] + store[i - 2]);
进一步归纳便可得出上式。
更详细的见:http://www.cnblogs.com/skyivben/archive/2008/07/04/1235062.html
方法二:暴力求解
static int DPTotal(int k,int n) { //dp[i,j]用于记录第i位第j个值得个数 int[,] dp = new int[n+1, k]; for (int i = 1; i < k; i++) dp[1, i] = 1; for(int i=2;i<n+1;i++) for(int j=0;j<k;j++) { if (j == 0) for(int m=1;m<k;m++) dp[i, j] += dp[i - 1, m]; if(j!=0) for (int m = 0; m < k; m++) dp[i, j] += dp[i - 1, m]; } int sum=0; for (int i = 0; i < k; i++) sum += dp[n, i]; return sum; }
主要知识点:用数组记录每个结果。
但比较奇怪的发现:方法2既然比方法1用时更短(感觉明显不正常吧!!!)
上面是方法2的结果=。=
时间: 2024-10-15 16:44:01