1.密码脱落
dp 结果是总长度-最大回文串的长度

#include<bits/stdc++.h>
using namespace std;
typedef pair<double,double>PII;
typedef long long ll;
const int N=1010;
int n,k;
int f[N][N];
char s[N];
int main()
{
scanf("%s",s);
n=strlen(s);
for(int len=1;len<=n;len++)
for(int i=0;i+len-1<n;i++)
{
int j=i+len-1;
if(len==1) f[i][j]=1;
else {
f[i][j]=max(f[i+1][j],f[i][j-1]);
if(s[i]==s[j])
f[i][j]=max(f[i][j],f[i+1][j-1]+2);
}
}
cout<<n-f[0][n-1]<<endl;
return 0;
}
2.生命之树
树形dp
#include<bits/stdc++.h>
using namespace std;
typedef pair<double,double>PII;
typedef long long ll;
const int N=100010,M=2*N;
int e[M],ne[M],h[N],w[M];
int idx;
ll f[N];
int n;
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u,int father)
{
f[u]=w[u];
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(j!=father)
{
dfs(j,u);
f[u]+=max(0ll,f[j]);
}
}
}
int main()
{
scanf("%d",&n);
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
for(int i=1;i<=n-1;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
dfs(1,-1);
ll res=f[1];
for(int i=2;i<=n;i++) res=max(res,f[i]);
cout<<res<<endl;
return 0;
}
线性代数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3;
int n,m;
int a[N][N]={
{0,1,0},
{1,1,1},
{0,0,1}
};
void mul(int a[][N],int b[][N])
{
int tmp[N][N]={0};
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
for(int k=0;k<N;k++)
tmp[i][j]=(tmp[i][j]+(ll)a[i][k]*b[k][j])%m;
memcpy(a,tmp,sizeof tmp);
}
int main()
{
scanf("%d%d",&n,&m);
int f1[N][N]={1,1,1};
n--;
while(n)
{
if(n&1) mul(f1,a); //相当于res*a操作
mul(a,a); //相当于快速幂里面的a*a操作
n>>=1;
}
cout<<f1[0][2]<<endl;
return 0;
}
4.括号配对

#include <cstdio>
#include <iostream>
using namespace std;
const int N = 110, INF = 1e8;
int f[N][N];
bool is_match(char l, char r) {
if (l == '(' && r == ')') return true;
if (l == '[' && r == ']') return true;
return false;
}
int main() {
string s; cin >> s;
int n = s.size();
for (int len = 1; len <= n; len ++) {
for (int l = 0; l + len - 1 < n; l ++) {
int r = l + len - 1; f[l][r] = INF;
if (is_match(s[l], s[r])) f[l][r] = f[l + 1][r - 1];
if (r >= 1) f[l][r] = min(f[l][r], min(f[l][r - 1], f[l + 1][r]) + 1);
for (int i = l; i < r; i ++)
f[l][r] = min(f[l][r], f[l][i] + f[i + 1][r]);
}
}
return cout << f[0][n - 1] << endl, 0;
}
5.旅游规划
树形dp
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 2e5 + 10, M = 4e5 + 10;
int h[N], e[M], ne[M], idx;
int d1[N], d2[N], p1[N], up[N], maxd;
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs_d(int u, int fa) {
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j != fa) {
dfs_d(j, u);
int distance = d1[j] + 1;
if (distance > d1[u]) {
d2[u] = d1[u], d1[u] = distance;
p1[u] = j;
}
else if (distance > d2[u]) d2[u] = distance;
}
}
maxd = max(maxd, d1[u] + d2[u]);
}
void dfs_u(int u, int fa) {
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j != fa) {
up[j] = up[u] + 1;
if (p1[u] == j) up[j] = max(up[j], d2[u] + 1);
else up[j] = max(up[j], d1[u] + 1);
dfs_u(j, u);
}
}
}
int main() {
int n; scanf("%d", &n);
memset(h, -1, sizeof h);
for (int i = 0; i < n - 1; i ++) {
int a, b; scanf("%d%d", &a, &b);
add(a, b), add(b, a);
}
dfs_d(0, -1), dfs_u(0, -1);
for (int i = 0; i < n; i ++) {
int d[3] = {d1[i], d2[i], up[i]};
sort(d, d + 3);
if (d[1] + d[2] == maxd) printf("%d\n", i);
}
return 0;
}
6.垒骰子
dp+矩阵相乘快速幂优化
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 6, MOD = 1e9 + 7;
int get(int x) {
if (x >= 3) return x - 3;
return x + 3;
}
void mul(int c[][N], int a[][N], int b[][N]) { //c = a * b
static int t[N][N]; memset(t, 0, sizeof t);
for (int i = 0; i < N; i ++)
for (int j = 0; j < N; j ++)
for (int k = 0; k < N; k ++)
t[i][j] = (t[i][j] + (LL)a[i][k] * b[k][j]) % MOD;
memcpy(c, t, sizeof t);
}
int main() {
int n, m; scanf("%d%d", &n, &m);
int a[N][N];
for (int i = 0; i < N; i ++)
for (int j = 0; j < N; j ++)
a[i][j] = 4;
while (m --) {
int x, y; scanf("%d%d", &x, &y);
x --, y --;
a[x][get(y)] = 0;
a[y][get(x)] = 0;
}
int f[N][N] = {4, 4, 4, 4, 4, 4};
for (int i = n - 1; i; i >>= 1) {
if (i & 1) mul(f, f, a);
mul(a, a, a);
}
int res = 0;
for (int i = 0; i < N; i ++) res = (res + f[0][i]) % MOD;
return printf("%d\n", res), 0;
}