藍橋杯 ADV-205算法提高 拿糖果(動態規划)


問題描述
媽媽給小B買了N塊糖!但是她不允許小B直接吃掉。
  假設當前有M塊糖,小B每次可以拿P塊糖,其中P是M的一個不大於根號下M的質因數。這時,媽媽就會在小B拿了P塊糖以后再從糖堆里拿走P塊糖。然后小B就可以接着拿糖。
  現在小B希望知道最多可以拿多少糖。
輸入格式
  一個整數N
輸出格式
  最多可以拿多少糖
樣例輸入
15
樣例輸出
6
數據規模和約定
N <= 100000

分析:動態規划問題~~首先呢~創建一個滿足不大於根號下最大值MAXN的素數表,然后對素數表里面的數逐個遍歷~
構建一個dp[i]數組,表示當糖果數量為i的時候所能拿的最多的糖果數量~
對於dp[i]的值:因為小B只能每次拿不大於根號下i的質因數,遍歷素數表中滿足條件的素數(prime[j] <= sqrt(i) && i % prime[j] == 0),更新dp[i]的值為(dp[i-2*prime[j]] + prime[j])的最大值~

即:dp[i] = max(dp[i], dp[i-2*prime[j]] + prime[j]);

#include <iostream>
#include <cmath>
using namespace std;
int prime[50000];
int dp[100005];
int book[100005];
int cnt = 0;

void create() {
int len = sqrt(100005);
for(int i = 2; i <= len; i++) {
if(book[i] == 0) {
prime[cnt++] = i;
for(int j = i * i; j <= len; j = j + i)
book[j] = 1;
}
}
}

int main() {
create();
int n;
cin >> n;
for(int i = 1; i <= n; i++) {
for(int j = 0; j < cnt; j++) {
if(prime[j] > sqrt(i))
break;
if(i % prime[j] == 0)
dp[i] = max(dp[i], dp[i-2*prime[j]] + prime[j]);
}
}
cout << dp[n];
return 0;
}



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: