看题传送门门:http://poj.org/problem?id=1163
困死了。。。。QAQ
普通做法,从下往上,可得状态转移方程为:
dp[i][j]= a[i][j] + max (dp[i+1][j] , dp[i+1][j+1] );
#include<cstdio> #include<cstring> int a[101][101]; int dp[101][101]; int main() { int n; while(~scanf("%d",&n)) { memset(a,0,sizeof(a)); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) scanf("%d",&a[i][j]); for(int i=1;i<=n;i++) dp[n][i]=a[n][i]; for(int i=n-1;i>=1;i--) { for(int j=1;j<=i;j++) dp[i][j]= a[i][j] + (dp[i+1][j] > dp[i+1][j+1]? dp[i+1][j]:dp[i+1][j+1]); } printf("%d\n",dp[1][1]); } }
记忆化搜索,本题数据量小,与上面的都是0ms,但记忆化搜索保证每个子结点只访问一次,速度应该更快。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int a[101][101]; int dp[101][101]; int n; int d(int i,int j) { if(dp[i][j]>=0) return dp[i][j]; return dp[i][j]= a[i][j] + (i==n ? 0: max ( d(i+1,j) ,d(i+1,j+1))); } int main() { while(~scanf("%d",&n)) { memset(a,0,sizeof(a)); memset(dp,-1,sizeof(dp)); for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) scanf("%d",&a[i][j]); d(1,1); printf("%d\n",dp[1][1]); } }
尝试使用宏定义让程序变得简洁而优雅
#include<cstdio> #include<cstring> #define F(i,n) for(int i=1;i<=n;i++) int a[101][101]; int dp[101][101]; int n; int main() { while(~scanf("%d",&n)) { memset(a,0,sizeof(a)); memset(dp,-1,sizeof(dp)); F(i,n) F(j,i) scanf("%d",&a[i][j]); F(i,n) dp[n][i]=a[n][i]; for(int i=n-1;i>=1;i--) { F(j,i) dp[i][j]= a[i][j]+ (dp[i+1][j] > dp[i+1][j+1]? dp[i+1][j]:dp[i+1][j+1]); } printf("%d\n",dp[1][1]); } }