您的位置:首页 > 教育 > 锐评 > 交互设计的方法和技巧_计算机入门基础知识_网络营销是什么_买外链有用吗

交互设计的方法和技巧_计算机入门基础知识_网络营销是什么_买外链有用吗

2025/4/27 17:35:27 来源:https://blog.csdn.net/2302_80329073/article/details/147462692  浏览:    关键词:交互设计的方法和技巧_计算机入门基础知识_网络营销是什么_买外链有用吗
交互设计的方法和技巧_计算机入门基础知识_网络营销是什么_买外链有用吗

DP 即动态规划(Dynamic Programming),是一种通过把原问题分解为相对简单的子问题,并保存子问题的解来避免重复计算,从而解决复杂问题的算法策略。以下从几个方面简述动态规划:

基本思想

动态规划的核心在于 “分治” 和 “最优子结构”。它将一个复杂问题分解为一系列相互关联的子问题,通过求解子问题并保存其解,避免对相同子问题的重复求解,从而减少计算量。同时,原问题的最优解可以由子问题的最优解组合而成,这就是最优子结构性质。

适用条件

  • 最优子结构性质:问题的最优解包含其子问题的最优解。即可以通过子问题的最优解推导出原问题的最优解。例如,在背包问题中,对于一个容量为 W 的背包和 n 个物品,要得到其最优装法,可以先考虑容量为 W - w[i]w[i] 为第 i 个物品的重量)的背包和前 n - 1 个物品的最优装法。
  • 子问题重叠性质:在求解过程中,会多次遇到相同的子问题。动态规划通过保存子问题的解,避免了对这些子问题的重复计算,从而提高了效率。比如在斐波那契数列的计算中,直接递归计算会有大量重复的子问题计算,而使用动态规划可以避免这种情况。

求解步骤

  1. 定义状态:明确问题的状态表示,即如何用一个或多个变量来描述子问题。例如,在最长上升子序列问题中,可以定义状态 dp[i] 表示以第 i 个元素结尾的最长上升子序列的长度。
  2. 确定状态转移方程:根据问题的最优子结构性质,找出状态之间的转移关系。状态转移方程描述了如何从子问题的解推导出原问题的解。例如,在最长上升子序列问题中,状态转移方程为 dp[i] = max(dp[j] + 1) (0 <= j < i 且 a[j] < a[i])
  3. 初始化:确定初始状态的值,这些初始状态是问题的边界条件。例如,在斐波那契数列的动态规划求解中,dp[0] = 0dp[1] = 1 就是初始状态。
  4. 计算顺序:根据状态转移方程,确定计算状态的顺序,一般是从简单的子问题开始,逐步求解更复杂的问题。

应用场景

动态规划在很多领域都有广泛的应用,常见的问题包括:

  • 背包问题:如 0 - 1 背包问题、完全背包问题等,用于在一定的约束条件下选择物品,使得总价值最大。
  • 最长公共子序列问题:找出两个序列中最长的公共子序列,在生物信息学、版本控制等领域有应用。
  • 最短路径问题:如 Floyd - Warshall 算法,用于求解图中任意两点之间的最短路径。
  • 资源分配问题:在多个项目或任务之间分配资源,以达到最优的效益。

目录

1087

题目

思路

代码详细步骤

动态规划初始化

状态转移

找出最大值

代码

1203

题目

思路

代码

1003

题目

思路

代码


1087

题目

思路

动态规划算法的核心在于将原问题分解为一系列子问题,并通过求解子问题来得到原问题的解。在这个问题中,我们定义状态 dp[i] 表示以第 i 个元素结尾的最长上升子序列的最大和。通过遍历序列中的每个元素,我们可以根据之前的状态来更新当前状态,最终找出所有状态中的最大值,即为最长上升子序列的最大和。

代码详细步骤

动态规划初始化
  • dp[0]=a[0];:将 dp[0] 初始化为 a[0],因为以第一个元素结尾的最长上升子序列就是它本身,其和就是 a[0]
状态转移
  • 外层循环 for(int i = 1; i < n; i++):遍历数组中的每个元素,从第二个元素开始。
  • dp[i]=a[i];:将 dp[i] 初始化为 a[i],表示以第 i 个元素结尾的最长上升子序列至少包含该元素本身。
  • 内层循环 for(int j = 0; j < i; j++):遍历当前元素 a[i] 之前的所有元素。
  • if(a[i]>a[j]):判断 a[i] 是否大于 a[j],如果满足条件,说明可以将 a[i] 接到以 a[j] 结尾的最长上升子序列后面。
  • dp[i]=max(a[i]+dp[j],dp[i]);:更新 dp[i] 的值,取 a[i] + dp[j] 和 dp[i] 中的最大值。a[i] + dp[j] 表示将 a[i] 接到以 a[j] 结尾的最长上升子序列后面得到的新子序列的和。
找出最大值
  • int maxnum=-1e9;:将 maxnum 初始化为一个较小的值 -1e9,确保后续找到的任何 dp[i] 值都能更新 maxnum
  • for(int i = 0; i < n; i++){ maxnum=max(maxnum,dp[i]); }:遍历 dp 数组,找出其中的最大值。

代码

#include<iostream>
#include<algorithm>
using namespace std;
int dp[1010],a[1010],n; 
int main(){while(cin>>n&&n){for(int i=0;i<n;i++){cin>>a[i];}dp[0]=a[0];for(int i=1;i<n;i++){dp[i]=a[i];for(int j=0;j<i;j++){if(a[i]>a[j]){dp[i]=max(a[i]+dp[j],dp[i]);}}}int maxnum=-1e9;for(int i=0;i<n;i++){maxnum=max(maxnum,dp[i]);}cout<<maxnum<<endl;}return 0;
}

1203

题目

思路

外层循环 for(int i = 0; i < m; i++):遍历每一个物品。

内层循环 for(int j = n; j >= a[i]; j--):从背包的总容量 n 开始,倒序遍历到当前物品的重量 a[i]。倒序遍历是为了保证每个物品只被选择一次,这是 0 - 1 背包问题的常见处理方式。

状态转移方程 dp[j]=max(dp[j],dp[j-a[i]]+prob[i]-dp[j-a[i]]*prob[i]);

dp[j] 表示不选择当前物品 i 时,背包容量为 j 的最大成功概率。

dp[j - a[i]] 表示在不放入当前物品 i 时,背包容量为 j - a[i] 的最大成功概率。

dp[j - a[i]] + prob[i] - dp[j - a[i]] * prob[i] 表示选择当前物品 i 时的成功概率。这里基于概率的计算原理,假设物品的成功是相互独立事件,使用公式 P(A 或 B) = P(A) + P(B) - P(A) * P(B) 来计算选择当前物品后的成功概率。

通过 max 函数取两者中的最大值更新 dp[j]

代码

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
double dp[N];
double prob[N];
int a[N];
int n,m;
int main(){while(cin>>n>>m){if(n==0 && m==0) break;for(int i=0;i<m;i++){cin>>a[i]>>prob[i];}memset(dp,0,sizeof(dp));for(int i=0;i<m;i++){for(int j=n;j>=a[i];j--){dp[j]=max(dp[j],dp[j-a[i]]+prob[i]-dp[j-a[i]]*prob[i]);}}printf("%.1lf%%\n",dp[n]*100);}return 0;
}

1003

题目

思路

状态转移方程 dp[j]=max(dp[j],dp[j-a[i]]+prob[i]-dp[j-a[i]]*prob[i]);

dp[j] 表示不选择当前物品 i 时,背包容量为 j 的最大成功概率。

dp[j - a[i]] 表示在不放入当前物品 i 时,背包容量为 j - a[i] 的最大成功概率。

dp[j - a[i]] + prob[i] - dp[j - a[i]] * prob[i] 表示选择当前物品 i 时的成功概率。这里基于概率的计算原理,假设物品的成功是相互独立事件,使用公式 P(A 或 B) = P(A) + P(B) - P(A) * P(B) 来计算选择当前物品后的成功概率。

通过 max 函数取两者中的最大值更新 dp[j]

代码

#include<iostream>
using namespace std;
int n,m,l,r,maxnum,sum,temp,num;
int main(){cin>>n;for(int i=0;i<n;i++){l=0,r=0,temp=1,maxnum=-20000,sum=0;cin>>m;for(int j=1;j<=m;j++){cin>>num;sum+=num;if(sum>maxnum){r=j;maxnum=sum;l=temp;}if(sum<0){temp=j+1;sum=0;}}cout<<"Case "<<(i+1)<<":"<<endl<<maxnum<<" "<<l<<" "<<r<<endl;if(i<n-1) cout<<endl;}return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com