题目链接
https://vjudge.net/contest/413174#problem/B
解题思路
dp。
dp[i][j]表示以点(i,j)为树顶的树的个数,最后求一下所有位置的点为树顶能构成的树的个数之和,即为答案。
转移方程:开始所有为 * 的位置全部初始化为1,dp[i][j]+=min{dp[i+1][j-1],dp[i+1][j],dp[i+1][j+1]}
注意:
1.边界;
2.因为给出的是n * m的范围,所以我们要用一维数组存储二维信息,不细说了,一维数组的下标整除m表示行坐标,取余m表示列坐标,行列坐标均从0开始。dp数组要设置成一维的。
3.一个一个输入字符的时候,也要注意getchar收回回车。
AC代码
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=300000; ll dp[N]; char mp[N]; int main() { int t; cin>>t; while(t--) { memset(dp,0,sizeof dp); ll ans=0; int n,m,k=0; cin>>n>>m; getchar();//getchar()!! for(int i=0;i<n;i++,getchar())//getchar()!! for(int j=0;j<m;j++) scanf("%c",&mp[i*m+j]); for(int i=n-1;i>=0;i--) for(int j=0;j<m;j++) { if(mp[i*m+j]=='.') continue; dp[i*m+j]=1; if(i!=n-1 && j!=0 && j!=m-1) dp[i*m+j]+=min(dp[(i+1)*m+(j-1)],min(dp[(i+1)*m+j],dp[(i+1)*m+j+1])); ans+=dp[i*m+j]; } // for(int i=0;i<n;i++,cout<<endl) // for(int j=0;j<m;j++) // cout<<dp[i*m+j]<<' '; cout<<ans<<endl; } }
总结
不小心看到了是dp
直接一套组合拳,写完了,就是处理边界和数组存储花了好长时间。