第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定

動(dòng)態(tài)規(guī)劃——看似dp的貪心問題最大乘積(藍(lán)橋杯試題集)

標(biāo)簽:
算法

题目链接:


http://lx.lanqiao.cn/problem.page?gpid=T136


问题描述
  对于n个数,从中取出m个数,如何取使得这m个数的乘积最大呢?
输入格式
  第一行一个数表示数据组数
  每组输入数据共2行:
  第1行给出总共的数字的个数n和要取的数的个数m,1<=n<=m<=15,
  第2行依次给出这n个数,其中每个数字的范围满足:a[i]的绝对值小于等于4。
输出格式
  每组数据输出1行,为最大的乘积。
样例输入
1
5 5
1 2 3 4 2
样例输出
48 


一:首先要分离正负,两个负值乘积为正。做这道题时让我想起了按键盘http://blog.csdn.net/sm9sun/article/details/53241628

 与其一样的是,按键盘保留大小写两种状态,那么本题也要保留正负最大值两种状态

二:类似于01背包,我们把m当作容量,每个数的体积都是1

这样一来每个数都面临取或者不取两种状态,当我们遍历到第i个物品时,我们要保留在i个物品中取j个物品的最大正负值即可



#include<stdio.h>#include<math.h>double fmax(double a,double b){	return a>b?a:b;}double fmin(double a,double b){	return a<b?a:b;}int main(){	double a[20];double fdp[20][20][20];double dp[20][20][20];	int m,n,i,j,k,t;	scanf("%d",&t);	while(t--)	{		scanf("%d%d",&n,&m);for(i=1;i<=n;i++)		scanf("%lf",&a[i]);for(i=0;i<=n;i++)		for(j=0;j<=m;j++)	for(k=0;k<=j;k++)	{	dp[i][j][k]=1;		fdp[i][j][k]=1;	}	fdp[0][1][1]=dp[0][1][1]=a[1];	for(i=1;i<=n;i++)                   //遍历n个数{for(j=1;j<=m&&j<=i;j++)             //m为容量,从i个数中取j个数{        	for(k=1;k<=j;k++)           //k遍历当我容量上限为j时取不同个数的最大值,这里与01背包不同,取值必须达到m容量,不能小于        	{                           //所以每一个k都要记录下来if(a[i]>0){dp[i][j][k]=fmax(dp[i-1][j][k],dp[i-1][j-1][k-1]*a[i]);fdp[i][j][k]=fmin(fdp[i-1][j][k],fdp[i-1][j-1][k-1]*a[i]);}else{dp[i][j][k]=fmax(dp[i-1][j][k],fdp[i-1][j-1][k-1]*a[i]);fdp[i][j][k]=fmin(fdp[i-1][j][k],dp[i-1][j-1][k-1]*a[i]);}			// printf("%.0lf,%.0lf ",dp[i][j][k],fdp[i][j][k]);}//printf("---");}//printf("\n");}printf("%.0lf\n",dp[n][m][m]);}return 0;}


用dp思想的确可以解决这道题,不过后来看了网上的答案,发现其实还有更简单的方法,用贪心~


我们将正负数分组排序后,依次选取两个最大正值乘积,两个最大负值乘积即可~

注意,如果m为奇数时要再乘一个正数。



#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int main(){int t, n, m;int num[20];scanf("%d", &t);while(t--){scanf("%d %d", &n, &m);for(int i = 0; i < n; i++)scanf("%d", &num[i]);sort(num, num+n);int i, j, a, b;i = j = 0;long long ans = 1;while(m){a = num[i]*num[i+1];b = num[n-j-1]*num[n-j-2];if(a>=b && m>=2){ans*=a;i+=2;m-=2;}else{ans*=num[n-j-1];j++;m--;}}printf("%lld\n", ans);}return 0;}

所以说,也不能盲目的运用dp,有一些问题还是可以用贪心解决的。


點(diǎn)擊查看更多內(nèi)容
TA 點(diǎn)贊

若覺得本文不錯(cuò),就分享一下吧!

評(píng)論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評(píng)論
  • 收藏
  • 共同學(xué)習(xí),寫下你的評(píng)論
感謝您的支持,我會(huì)繼續(xù)努力的~
掃碼打賞,你說多少就多少
贊賞金額會(huì)直接到老師賬戶
支付方式
打開微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊(cè)有機(jī)會(huì)得

100積分直接送

付費(fèi)專欄免費(fèi)學(xué)

大額優(yōu)惠券免費(fèi)領(lǐng)

立即參與 放棄機(jī)會(huì)
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)

舉報(bào)

0/150
提交
取消