版权声明:欢迎指出文章不足之处~~~ https://blog.csdn.net/zhui_xiuge/article/details/80558889
1. 爬楼梯
//用组合数的方法比较拖沓
#include <iostream>
using namespace std;
const int N = 55;
int n;
unsigned dp[N]; //dp[i]:从阶梯0跳到n的方法数, 爆int
void solve() {
dp[1] = dp[0] = 1;
for (int i = 2; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2]; //可用快速矩阵幂
}
cout << dp[n] << '\n';
}
int main() {
cin >> n;
solve();
return 0;
}
2. 跳跃游戏2
#include <iostream>
#include <climits>
using namespace std;
const int N = 105;
const int INF = INT_MAX;
int n;
int jump_len[N];
int dp[N]; //从下标1到i最少跳跃次数(区别跳跃长度)
void read() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> jump_len[i];
}
void solve() {
//init
dp[1] = 0;
for (int i = 2; i <= n; i++) dp[i] = INF;
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
//dp[j]!=INF:可以从下标1跳到j位置
if (dp[j] != INF && jump_len[j] >= i - j && dp[j] + 1 < dp[i]) {
dp[i] = dp[j] + 1;
}
}
}
cout << dp[n] << '\n';
}
int main() {
read();
solve();
return 0;
}
3. 等和的分隔子集
#include <iostream>
using namespace std;
const int MAX_SUM = 391; //(39+1)*39/2
const int N = 40;
int n;
//dp[i][j]:区间[1,i]内,和为j的子集个数
unsigned dp[N][MAX_SUM]; //又爆int
//unsigned dp[MAX_SUM];
void solve() {
int sum = (n + 1)*n / 2;
if (sum % 2) cout << "0\n"; //奇数和无法划分
else {
int half_sum = sum / 2;
for (int j = 1; j <= half_sum; j++) dp[0][j] = 0;
//下面两条for语句可交换
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= half_sum; j++) {
//核心
if (i > j) dp[i][j] = dp[i - 1][j];
else if (i == j) {
dp[i][j] = dp[i - 1][j] + 1;
}
else {
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - i];
}
}
}
//对称:取结果的一半
cout << dp[n][half_sum] / 2 << '\n';
/*优化
dp[0] = 1; //init
for (int i = 1; i <= n; i++) {
for (int j = half_sum; j >= i; j--) {
//逆着推,新的dp[j]表示前面不包含i和包含i的情况之和
dp[j] += dp[j - i];
}
}
cout << dp[half_sum] / 2 << '\n';
*/
}
}
int main() {
cin >> n;
solve();
return 0;
}
- 2018/7/11 1:09
分析: dp[n][k]表示正整数n分解为不多于k个正整数相交形式的个数,则有:
这里仅对n > k的情形做以说明:
1.n恰好分解成k个整数,此时不易直接表示,但注意到分解的k个整数皆>=1,那么我们把分解的k个整数都减去1,即知可用dp[n-k][k]表示
2.n分解为小于k个整数,为dp[n][k-1]
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const int MAX_N = 305;
const int MAX_K = 305;
int n, k;
ll dp[MAX_N][MAX_K];
void solve() {
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= k; j++) {
if (j < i) dp[i][j] = dp[i][j - 1] + dp[i - j][j];
else if (j == i) {
dp[i][j] = dp[i][j - 1] + 1;
}
else dp[i][j] = dp[i][i];
}
}
/*for (int i = 1; i <= n; i++) {
for (int j = 1; j <= k; j++) {
if (dp[i][j] > INT64_MAX)
cout << "overleap!\n";
}
}*/
cout << dp[n][k] << '\n';
}
int main() {
cin >> n >> k;
solve();
return 0;
}
参照:
【1】等和的分隔子集:https://blog.csdn.net/z9550695/article/details/47339895
【2】程序设计:划分整数:https://blog.csdn.net/Go_Accepted/article/details/79762494