算法第三章作业
1. “挖地雷”动态规划分析:
1.1 递归方程式:
当 i=n 时,f[n]=w[n];
当 i>0 && i<n 时,f[i]=max{f[j]}+w[i],其中,j满足条件a[i][j]=true。
1.2 给出填表法中表的维度、填表范围和填表顺序:
填表维度为一维,两个数组,即f和c数组,f从第n个往前填,同时将k地窖是i地窖的目标后继点以c[i]=k的形式保存下来;
1.3 分析该算法的时间和空间复杂度:
因为只需要填一维表所以时间复杂度为O(N),用了一个二维数组a[i][j]来保存i,j之间的关系,故空间复杂度为O(N^2)。
2. 对动态规划算法的理解:
DP最大的特点就是对重复子问题的处理,其他的同分治法处理思路类似,都是转化为对最优子问题的求解。
3. 结对编程情况:
挺好的,一开始存在一些思路上的问题,经过讨论都能克服。
代码展示:
#include<iostream> #include<cstring> using namespace std; int main() { long f[201]={0},w[201],c[201]={0}; bool a[201][201]={0}; long i,j,n,x,y,l,k,max; while(cin>>n) { memset(f,0,sizeof(f)); memset(w,0,sizeof(w)); memset(c,0,sizeof(c)); memset(a,false,sizeof(a)); for(i=1;i<=n;i++) cin>>w[i]; //输入每个地窖中的地雷数 do { cin>>x>>y; if((x!=0)&&(y!=0)) a[x][y]=true; } while((x!=0)&&(y!=0)); f[n]=w[n]; //从后面的f[n]往前逐个找出所有的f[i] for(i=n-1;i>=1;i--) { l=0;k=0;//l要置零,很重要 for(j=i+1;j<=n;j++) if((a[i][j])&&(f[j]>l)) { l=f[j]; k=j; } f[i]=l+w[i]; //保存从第i个地窖起能挖到最大地雷数 c[i]=k; //k地窖是i地窖最优路径的后继点 } k=1; for(j=2;j<=n;j++) if(f[j]>f[k]) k=j; max=f[k]; cout<<k; k=c[k]; while(k!=0) { cout<<"-"<<k; k=c[k]; } cout<<endl; cout<<max<<endl; } return 0; }
因为只需要填一维表所以时间复杂度为O(N),用了一个二维数组a[i][j]来保存i,j之间的关系,故空间复杂度为O(N^2)。