Codeforces - 909C - Python Indentation - 简单dp
http://codeforces.com/problemset/problem/909/C
好像以前做过,但是当时没做出来,看了题解也不太懂。
一开始以为只有上面的for有了循环体,这里的statement就可以随便放,但其实并不是这样,statement的位置会取消比它缩进更多或相等的for的可append性。所以设计dp顺序的时候要用dp[i][j]表示第i行剩余可选for循环数量为j的选法数。那么递推公式也不难(才怪),看看代码就好了。
有几个可以优化的,一个是滚动数组,另一个是线性求前缀和然后均摊O(1)减少一个维度的时间复杂度。
注意读入%c之前要加一个空格来过滤前面还保留在流中的换行符。
#include<bits/stdc++.h> using namespace std; #define ll long long ll dp[5005][5005]; char ch[5005]; int n; int p=1000000007; int main(){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf(" %c",&ch[i]); //printf("%c\n",ch[i]); } int cntf=0; if(ch[0]=='f') cntf++; dp[0][cntf]=1; //可跟随的f的数量 /*for(int j=0;j<=cntf;j++){ printf("dp[%d][%d]=%lld\n",0,j,dp[0][j]); } printf("\n");*/ for(int i=1;i<n;i++){ if(ch[i]=='f'){ cntf++; if(i-1>=0&&ch[i-1]=='f'){ //dp[i]=dp[i-1]; //不得不跟随 for(int j=1;j<=cntf;j++){ dp[i][j]=dp[i-1][j-1]; } } else if(i-1>=0&&ch[i-1]=='s'){ //任选一个f进行跟随 ll sum=0; for(int j=0;j<=cntf-1;j++){ sum=(sum+dp[i-1][j])%p; } ll presum=0; for(int j=1;j<=cntf;j++){ dp[i][j]=(sum-presum+p)%p; presum=(presum+dp[i-1][j-1])%p; } } } else{ if(i-1>=0&&ch[i-1]=='f'){ //dp[i]=dp[i-1]; //不得不跟随 for(int j=0;j<=cntf;j++){ dp[i][j]=dp[i-1][j]; } } else if(i-1>=0&&ch[i-1]=='s'){ //任选一个f进行跟随 ll sum=0; for(int j=0;j<=cntf;j++){ sum=(sum+dp[i-1][j])%p; } ll presum=0; for(int j=0;j<=cntf;j++){ dp[i][j]=(sum-presum+p)%p; presum=(presum+dp[i-1][j])%p; } } } /*for(int j=0;j<=cntf;j++){ printf("dp[%d][%d]=%lld\n",i,j,dp[i][j]); } printf("\n");*/ } ll sum=0; for(int j=0;j<=cntf;j++){ sum=(sum+dp[n-1][j])%p; } printf("%lld\n",sum); }
---恢复内容结束---