社区讨论

区间DP求调

P6333 [COCI 2007/2008 #1] ZAPIS参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@mdlmj0qn
此快照首次捕获于
2025/07/27 19:56
7 个月前
此快照最后确认于
2025/11/04 03:38
4 个月前
查看原帖
rt。TLE on #5~#10。
具体思路是令 dpi,jdp_{i,j}[i,j][i,j] 的方案数,枚举 k(ikj)k(i\le k\le j) 使得 aia_iaka_k 匹配,用递归+记忆化实现。
CPP
#include <bits/stdc++.h>
using namespace std;

#define int __int128

inline int Read() {
  int x = 0,f = 1;
  char c = getchar();
  for(;c < '0' || c > '9';c = getchar()) f ^= (c == '-');
  for(;c >= '0' && c <= '9';c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
  return f ? x : -x;
}

void Print(int x,int flag = 1) {
  if(!x) return;
  Print(x / 10,0);
  putchar(x % 10 + '0');
  if(flag) puts("");
}

const int _ = 505;

int n;
string s;
int a[_],dp[_][_],vis[_][_],flag[_][_];

int Count(int x,int y) {
  if(x > 3 || (y != 0 && y < 4)) return 0; 
  if(x == 0 && y == 0) return 3;
  if(x == 0 || y == 0) return 1;
  if(x == y - 3) return 1;
  return 0;
}

int DP(int x,int y) {
  if(x > y || dp[x][y]) return dp[x][y];
  for(int i = x + 1;i <= y;i += 2) {
	dp[x][y] += Count(a[x],a[i]) * DP(x + 1,i - 1) * (i + 1 > y ? 1 : DP(i + 1,y));
	if(dp[x][y] > 100000) dp[x][y] %= 100000,flag[x][y] = 1;
  }
  return dp[x][y];
}

signed main() {
  n = Read();
  cin >> s,s = ' ' + s;
  map<char,int> mp;
  mp['('] = 1,mp['['] = 2,mp['{'] = 3,mp[')'] = 4,mp[']'] = 5,mp['}'] = 6;
  for(int i = 1;i <= n;i++) {
  	a[i] = mp[s[i]];
  	dp[i][i - 1] = 1;
  }
  dp[n + 1][n] = 1;
  DP(1,n);
  if(flag[1][n]) {
  	if(dp[1][n] < 10000) putchar('0');
  	if(dp[1][n] < 1000) putchar('0');
  	if(dp[1][n] < 100) putchar('0');
  	if(dp[1][n] < 10) putchar('0');
	Print(dp[1][n]);
  } else {
  	Print(dp[1][n]);
  }
  return 0;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...