简简单单,没人写题解,我来,(我不知道如何发题解,大神们帮个忙。。。)
题目描述
在一个 N 个节点的无向图(没有自环、重边)上,每个点都有一个符号,可能是数字,也可能是加号、减号、乘号、除号、小括号。你要在这个图上数一数,有多少种走恰好 K 个节点的方法,使得路过的符号串起来能够得到一个算数表达式。路径的起点和终点可以任意选择。
所谓算数表达式,就是由运算符连接起来的一系列数字。括号可以插入在表达式中以表明运算顺序。
注意,你要处理各种情况,比如数字不能有多余的前导 0,减号只有前面没有运算符或数字的时候才可以当成负号,括号可以任意添加(但不能有空括号),0可以做除数(我们只考虑文法而不考虑语意),加号不能当正号。
例如,下面的是合法的表达式:
-0/0
((0)+(((2*3+4)+(-5)+7))+(-(2*3)*6))
而下面的不是合法的表达式:
001+0
1+2(2)
3+-3
--1
+1
()
输入格式
第一行三个整数N,M,K,表示点的数量,边的数量和走的节点数。
第二行一个字符串,表示每个点的符号。
接下来M行,每行两个数,表示一条边连的两个点的编号。
1≤N≤20,0≤M≤N×(N-1)/2,0≤K≤30
输出格式
输出一行一个整数,表示走的方法数。这个数可能比较大,你只需要输出它模1000000007的余数即可。
输入输出样例
输入 #1复制
6 10 3 )(1*+0 1 2 1 3 1 4 2 3 3 4 2 5 3 5 3 6 4 6 5 6
输出 #1复制
10
说明/提示
一共有10条路径,构成的表达式依次是101, (1), 1+1, 1+0, 1*1, 1*0, 0+0, 0+1, 0*0, 0*1
上代码
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
const int MAXN = 40;
const int MOD = 1000000007;
int N,M,K;
char s[30];
bool is_digit(char c)
{
return c >= '0' && c <= '9';
}
bool is_operator(char c)
{
return c == '+' || c == '-' || c == '*' || c == '/';
}
int g[MAXN][MAXN];
int dp[MAXN][MAXN][MAXN][2];
int dfs(int u, int k, int p, int z)
{
if(dp[u][k][p][z] >= 0)
return dp[u][k][p][z];
int ret = 0;
if(k == K){
if((p==0) && !is_operator(s[u]))
ret = 1;
else
ret = 0;
return dp[u][k][p][z] = ret;
}
for(int v = 0; v < N; ++v){
if(g[u][v]){
if(is_digit(s[v])){
if(is_digit(s[u]) && !z){
ret += dfs(v, k+1, p, 0);
ret %= MOD;
}
else if(is_operator(s[u]) || s[u] == '('){
ret += dfs(v, k+1, p, s[v] == '0');
ret %= MOD;
}
}
else if(s[v] == '('){
if(s[u] == '(' || is_operator(s[u])){
ret += dfs(v, k+1, p+1, 0);
ret %= MOD;
}
}
else if(s[v] == ')'){
if(p > 0 && (is_digit(s[u]) || s[u] == ')')){
ret += dfs(v, k+1, p-1, 0);
ret %= MOD;
}
}
else {
if(is_digit(s[u])){
ret += dfs(v, k+1, p, 0);
ret %= MOD;
}
if(s[u] == ')' || (s[u] == '(' && s[v] == '-')){
ret += dfs(v, k+1, p, 0);
ret %= MOD;
}
}
}
}
return dp[u][k][p][z] = ret;
}
int main()
{
cin >> N >> M >> K;
cin >> s;
memset(g,0,sizeof(g));
memset(dp, -1, sizeof(dp));
for(int i = 1; i <= M; ++i){
int u,v;
cin >> u >> v;
u--;
v--;
g[u][v] = g[v][u] = 1;
}
int ans = 0;
for(int u = 0; u < N; ++u){
if(s[u] == '('){
ans += dfs(u,1,1,0);
ans %= MOD;
}
else if(s[u] == '-'){
ans += dfs(u,1,0,0);
ans %= MOD;
}
else if(is_digit(s[u])){
ans += dfs(u,1,0,s[u]=='0');
ans %= MOD;
}
}
cout << ans << endl;
return 0;
}
大家6.1开心不,开心的留个言。
886