题目链接
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
直接一套组合拳,写完了,就是处理边界和数组存储花了好长时间。

京公网安备 11010502036488号