九度OJ 教程99 动态规划之《搬寝室》
2013-02-22 21:03
190 查看
题目地址:http://ac.jobdu.com/problem.php?cid=1040&pid=98
//九度OJ 教程99 动态规划之《搬寝室》 //http://ac.jobdu.com/problem.php?cid=1040&pid=98 #include<stdio.h> #include<string.h> #include<stdlib.h> #define MAXS 2002 int min(int a,int b)//该函数保证在a、b俩数最多有一个负数(俩大数相加导致的负数)存在的情况下,返回一个正的较小的数。 { if(b<0)return a;//b<0是为了防止俩大数相加出现负数而导致的误判。 if(b<a)return b; return a; } int list[MAXS],dp[MAXS][MAXS]; int cmp(const void *a,const void *b)//按照从小到大排序。 { int *aa=(int *)a,*bb=(int *)b; return *aa-*bb; } int main() { int k,n,i,j; while(~scanf("%d %d",&n,&k)) { memset(list,0x7f,MAXS*sizeof(int)); memset(dp,0x7f,MAXS*MAXS*sizeof(int)); memset(dp,0,MAXS*sizeof(int));//只把第一行清零。即:任何前j个物品取i=0对后的疲劳度都是0 for(j=1;j<=n;j++)scanf("%d",&list[j]); qsort(list+1,n+1,sizeof(list[0]),cmp); for(i=1;i<=k;i++) { for(j=2*i;j<=n;j++) { dp[i][j]=min(dp[i][j-1],dp[i-1][j-2]+(list[j]-list[j-1])*(list[j]-list[j-1]));//此处与大神代码不同。我的思路是不用判断j==2*i。因为如果j==2*i,则j-1必小于2*i。根据上面的memset()函数,dp[i][2*i-1]这个值非常大,已经大于2000*2^16这个值了(2000是n的规模,2^16是任意俩重量相减再平方的疲劳值的最大值。)。而在这俩嵌套循环中,j的初值就设置成了2*i,下面修改也只是修改dp[i][j]的值,j只能++而不会减少,故没有机会修改dp[i][2*i-1]这个数的值。由于求的是min(),那么大的一个dp[i][2*i-1],本身就会被min函数搞掉。故,我认为,不用判断相等与否,依然可行。一句话总结:我理解的大神代码的意思为“如果j等于了2*i,那么dp[i][j-1]的值绝不能赋给dp[i][j]”,而我的意思是“由于上面的限定,dp[i][j]通过min函数赋值,则永远不会继承到前面dp[i][2*i-1]这个值。” }//结果竟然wrong了……我想不通…… } printf("%d\n",dp[k] ); } return 0; }
相关文章推荐
- 九度OJ 1086 最小花费--动态规划
- Special的——动态规划入门教程
- 九度OJ 1452 搬寝室 -- 动态规划
- 九度OJ 1453 Greedy Tino -- 动态规划
- 九度OJ 教程86 广度优先搜索解决迷宫问题之《胜利大逃亡》
- 九度OJ 教程89 递归+回溯之《Prime ring problem》
- 九度OJ 教程91 回溯算法之《全排列》
- 九度OJ 1086 最小花费--动态规划
- 九度OJ 1452 搬寝室 -- 动态规划
- 九度OJ 1453 Greedy Tino -- 动态规划
- 动态规划中级教程 377. Combination Sum IV
- 非常特别的一个动态规划新手教程
- //九度教程94 动态规划之不容易系列之一
- 九度OJ 教程85 求最大值 木有前兆输入时,的读取数据的方法
- 九度OJ 教程83 百鸡问题
- 九度OJ 教程88 递归解决之汉诺塔III
- 动态规划中级教程 279. Perfect Squares
- 【51nod 教程】最长单增子序列(LIS—动态规划)
- 九度OJ 教程15 排版类问题之叠筐
- 九度OJ 教程87 广度优先搜索之《非常可乐》