Lightoj 1157 数位DP

来源:互联网 发布:所有教材答案软件 编辑:程序博客网 时间:2024/05/19 12:13

A掉了poj1934 之后得到的思路。。。。可以点进去看一下那一题的思路:点击打开链接

这题是在那一题的基础上再用记忆化搜索来优化,不然会超时

我记得我一开始看过一个用递推上去的也行

注意:代码中的dps是二维的,我当时写的,我今天看的时候怎么想的想不明白,觉得应该是三维的啊,应该有一个长度的维度啊,但是刚刚在去抢基友煮的八宝粥的时候(ps;:大冬天的,武汉的宿舍很冷的。。。。。。。),突然就明白了,这个时候的dps所代表的一定是 i和j    的   最长公共的长度  的有多少种可能。。。不然就不科学了。。。而此时的最长长度是特定的。。。。。。●rz 就这样了。。。不知道下次再回想会不会不记嘚。。。哎,以前做数学也是,当时能证明出来,后来就忘了。。。。

AC代码如下:

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <set>#include <algorithm>using namespace std;char a[1100], b[1100];int lcm;int dp[1100][1100];int dps[1100][1100];int last1[1100][27], last2[1100][27];int lengtha, lengthb;void calc_lcm(){memset( dp, 0, sizeof( dp ) );for( int i = 1; i <= lengtha; i++ ){for( int j = 1; j <= lengthb; j++ ){if( a[i] == b[j] ){dp[i][j] = max( dp[i][j], dp[i-1][j-1] + 1 );}else{dp[i][j] = max( dp[i][j], max( dp[i-1][j], dp[i][j-1] ) );}}}lcm = dp[lengtha][lengthb];}int find_ans( int pos_a, int pos_b, int length ){if( length <= 0 ){return 1;}int ans = 0;if( dps[pos_a][pos_b] != -1 ){return dps[pos_a][pos_b];}if( pos_a > 0 && pos_b > 0 ){for( int i = 25; i >= 0; i-- ){int temp1 = last1[pos_a][i];int temp2 = last2[pos_b][i];if( dp[temp1][temp2] == length ){ans += find_ans( temp1 - 1, temp2 - 1, length - 1 );ans = ans % 1000007;}}}return dps[pos_a][pos_b] = ans;}int solve(){memset( last1, 0, sizeof( last1 ) );memset( last2, 0, sizeof( last2 ) );memset( dps, -1, sizeof( dps ) );for( int i = 1; i <= lengtha; i++ ){for( int j = 0; j < 26; j++ ){if( a[i] == ( 'a' + j ) ){last1[i][j] = i;}else{last1[i][j] = last1[i-1][j];}}}for( int i = 1; i <= lengthb; i++ ){for( int j = 0; j < 26; j++ ){if( b[i] == ( 'a' + j ) ){last2[i][j] = i;}else{last2[i][j] = last2[i-1][j];}}}return find_ans( lengtha, lengthb, lcm );}int main(){int T, Case = 1;cin >> T;while( T-- ){scanf( "%s%s", a + 1, b + 1 );lengtha = strlen( a + 1 );lengthb = strlen( b + 1 );calc_lcm();cout << "Case " << Case++ << ": " << solve() % 1000007 << endl;}return 0;}



0 0
原创粉丝点击