SRM528 DIV1 500

一个关于字符串计数的问题。
题意的描述很简洁,思路方向也很容易想——首先数据范围限定字符串长度最大为40,要把原串分为两个相等的子串,显然每个子串的长度最大为20,而且每个字符不是x就是o。。。所以很容易想到:求出x和o的个数,枚举所有可能的子串;或者可以直接用位运算,从0——2^20-1枚举一遍。然后计数方面看结构的话应该是dp。。。。但比赛的时候在dp上面悲剧了,我一直在想如何从前向后dp,边界设在前面。而官方题解给的是后向dp,边界设在了最后。。。对dp的理解又加深了,高兴~~突破思维定势,多角度看问题,把握根本。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;

typedef long long llg;

class SPartition{
public:
char w[22];
int n;
string str;
bool finish[22][22];
llg dp[22][22];
llg rec(int a, int b){
llg ans = dp[a][b];
if(!finish[a][b]){
if(a+b == n<<1){
if(a==n && b==n)
dp[a][b] = 1;
}
else{
if(str[a+b] == w[a]) dp[a][b] += rec(a+1, b);
if(str[a+b] == w[b]) dp[a][b] += rec(a, b+1);
}
finish[a][b] = true;
ans = dp[a][b];
}
return ans;
}
llg dfs(int p, int x, int o){
if(p == n){
memset(finish, false, sizeof(finish));
memset(dp, 0, sizeof(dp));
return rec(0, 0);
}
else{
llg ans = 0;
if(x > 0){
w[p] = 'x';
ans += dfs(p+1, x-1, o);
}
if(o > 0){
w[p] = 'o';
ans += dfs(p+1, x, o-1);
}
return ans;
}
}
llg getCount(string s){
int tx, to;
str = s;
n = s.length() / 2;
tx = to = 0;
for(int i = 0; i < s.length(); i++){
if(s[i] == 'x') tx++;
else to++;
}
if(tx%2!=0 || to%2!=0) return 0;
else return dfs(0, tx/2, to/2);
}
};



你可能感兴趣的:(div)