首页 > 代码库 > DP 简单题目练习
DP 简单题目练习
ZOJ 1234
这道题目我表示也还不是特别能理解。。。。还是太菜了T T
从后往前思考,因为只要后面有多的数在,那么C肯定是存在的,只要考虑是否把前两个数加在一起作为badness值这样两种情况来考虑
如果总数和3*j相同的话,那必然不用多考虑,它只能以前两个数的平方差作为badness值
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 int len[5005],dp[5005][1010]; 7 8 int main() 9 {10 int T,k,n;11 scanf("%d",&T);12 while(T--){13 scanf("%d%d",&k,&n);14 15 memset(dp,0x3f,sizeof(dp));16 for(int i=0;i<=n;i++)17 dp[i][0]=0;18 19 k+=8;20 for(int i=1;i<=n;i++)21 scanf("%d",len+i);22 //i表示从i这点开始一直取到末尾,j表示取的筷子组23 for(int i=n-2;i>=0;i--){24 for(int j=1;j<=k&&n-i+1>=3*j;j++){25 if(n-i+1 == 3*j)26 dp[i][j] = dp[i+2][j-1] + (len[i]-len[i+1])*(len[i]-len[i+1]);27 28 else if(n-i+1>3*j)29 //这个语句表示对于最前面的那个数选不选取有两种可能性,不选,选了那么必然还要选取相邻的数和它作为一组30 dp[i][j] = min(dp[i+1][j],dp[i+2][j-1] + (len[i]-len[i+1])*(len[i]-len[i+1]));31 }32 }33 34 printf("%d\n",dp[1][k]);35 }36 return 0;37 }38
ZOJ 1366
这道题目对于一种产品来说数量有多样,但我们直接用0-1背包做是会超时的,所以先把商品打包在一起,数量由1,2,4,8,16~这样叠加上去,也就是说,即使有1000个数量,也只需要数组用11个地址来保存即可。
再根据0-1背包求解,这里最好把dp[]数组设为1元的,dp过程就逆向思考,不然二元的太耗内存,会不会爆我也没试过
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int cnt;//表示产品的量 6 int price[120],dp[100005]; 7 8 //多重背包转化成0-1背包来求解 9 void change(int k,int pri)10 {11 int a=1;12 price[0]=0;13 while(k>a){14 price[++cnt] = a*pri;15 k-=a;16 a<<=1;17 }18 price[++cnt] = k*pri;19 }20 21 int main()22 {23 int cash,n,d,pri;24 25 while(~scanf("%d%d",&cash,&n)){26 cnt=0;27 memset(dp,0,sizeof(dp));28 29 for(int i=0;i<n;i++)30 {31 scanf("%d%d",&d,&pri);32 change(d,pri);33 }34 35 for(int i=1;i<=cnt;i++){36 for(int j=cash;j>=1;j--){37 if(j>=price[i])38 dp[j] = max(dp[j],dp[j-price[i]]+price[i]);39 }40 }41 42 printf("%d\n",dp[cash]);43 }44 return 0;45 }
DP 简单题目练习
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。