复杂DP

1.鸣人的影分身

ACWing1050. 鸣人的影分身
在这里插入图片描述
输入样例:

1
7 3

输出样例:

8

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 11;
int main()
{
    
    
    int T;
    scanf("%d", &T);
    while(T--)
    {
    
    
        int n, m;
        cin >> m >>n;
        int f[N][N] = {
    
    0};
        f[0][0] = 1;//边界  总和是0, 选0个数的方案数是1
        
        for(int i = 0; i <= m; i++)
         for(int j = 1;j <= n; j++)
         {
    
    
             f[i][j] = f[i][j-1];
             if(i >= j) f[i][j] += f[i-j][j];
         }
         printf("%d\n", f[m][n]);
    }
    return 0;
}

2.糖果

ACWing1047. 糖果
在这里插入图片描述
输入样例:

5 7
1
2
3
4
5

输出样例:

14

样例解释
Dzx的选择是2+3+4+5=14,这样糖果总数是7的倍数,并且是总数最多的选择。

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 110;
int f[N][N];//从i个数中选总数模k为j的方案中的最大值
int n, k;
int main()
{
    
    
   cin >>n >>k;
   memset(f,-0x3f,sizeof f);//f[0][1]、f[0][2]···无意义
   f[0][0] = 0;//本题求的是最大值而不是方案数,因此为0
   for(int i = 1; i <= n; i++)
   {
    
    
       int w;
       scanf("%d", &w);
       for(int j = 0; j <k; j++)
        f[i][j] = max(f[i-1][j], f[i-1][(j+k-w%k)%k]+w);
   }
   printf("%d\n", f[n][0]);
   return 0;
}

3.密码脱落

1222. 密码脱落
在这里插入图片描述
输入样例1:

ABCBA

输出样例1:

0

输入样例2:

ABDCDCBABC

输出样例2:

3

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1010;
char s[N];
int f[N][N];
int main()
{
    
    
    scanf("%s",s);
   int n = strlen(s);
    
    for(int len = 1; len <= n;len++)
    for(int l = 0;  l + len -1 <n; l++)
    {
    
    
        int r = l +len - 1;
        if(len == 1) f[l][r] = 1;
        else 
        {
    
    
            if(s[l] == s[r]) f[l][r] = f[l+1][r-1]+2;
            if(f[l][r-1] > f[l][r]) f[l][r] = f[l][r-1];
            if(f[l+1][r] > f[l][r]) f[l][r] = f[l+1][r];
        }
    }
    cout << n- f[0][n-1];
    return 0;
}

4.生命之树

AcWing1220. 生命之树
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N = 100010, M = N*2;
int n, w[N], h[N],e[M],ne[M],idx;
LL f[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 != -1; i = ne[i])
    {
    
    
        int j = e[i];
        if(j != father)
        {
    
    
            dfs(j,u);
            f[u] += max(0ll,f[j]);
        }
    }
}
int main()
{
    
    
    cin >>n;
    memset(h,-1,sizeof h);
    for(int i = 1; i <= n; i++) scanf("%d", &w[i]);
    
    for(int i = 0; i <n-1; i++)
    {
    
    
        int a, b;
        cin >> 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;
}

5. 斐波那契前 n 项和

AcWing1303. 斐波那契前 n 项和
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N =3;
int n,m;
void mul(int c[],int a[],int b[][N])
{
    
    
    int temp[N] = {
    
    0};
    for(int i = 0; i <N; i++)
     for(int j = 0; j <N; j++)
      temp[i] = (temp[i] +(LL)a[j]*b[j][i])%m;
      
      memcpy(c,temp,sizeof temp);
}

void mul(int c[][N],int a[][N], int b[][N])
{
    
    
    int temp[N][N]={
    
    0};
    for(int i = 0; i <N; i++)
     for(int j = 0; j < N; j++)
       for(int k = 0; k < N; k++)
        temp[i][j] = (temp[i][j] +(LL)a[i][k]*b[k][j])%m;
        
        memcpy(c,temp,sizeof temp);
}
int main()
{
    
    
   
   cin >> n >>m;
   int f1[N]={
    
    1,1,1};
   int a[N][N] = {
    
    {
    
    0,1,0},{
    
    1,1,1},{
    
    0,0,1}};
   n--;
   while(n)
   {
    
    
       if(n & 1) mul(f1,f1,a);
       mul(a,a,a);//a = a*a
       n >>= 1;
   }
   cout << f1[2] <<endl;
   return 0;
}

6. 包子凑数

AcWing1226. 包子凑数
在这里插入图片描述
输入格式
第一行包含一个整数 N。

接下来 N 行,每行包含一个整数 Ai。

输出格式
输出一个整数代表答案。

如果凑不出的数目有无限多个,输出INF。

数据范围
1≤N≤100,
1≤Ai≤100
输入样例1:

2
4
5

输出样例1:

6

输入样例2:

2
4
6

输出样例2:

INF

样例解释
对于样例1,凑不出的数目包括:1, 2, 3, 6, 7, 11。
对于样例2,所有奇数都凑不出来,所以有无限多个。
在这里插入图片描述

#include<iostream>
#include<algorithm>
using namespace std;
const int N = 10010;
int a[110];
bool f[110][N];
int gcd(int a,int b)
{
    
    
    return b?gcd(b,a%b):a;
}
int main()
{
    
    
    int n;
    cin >>n;
    int d = 0;
    for(int i = 1; i <= n; i++)
    {
    
    
        scanf("%d", &a[i]);
        d = gcd(d,a[i]);
    }
    
    if(d != 1) puts("INF");
    else 
    {
    
    
        f[0][0] = true;
        for(int i = 1; i <= n; i++)
         for(int j = 0;j <N; j++)
         {
    
    
             f[i][j] = f[i-1][j];
             if(j >= a[i]) f[i][j] |= f[i][j-a[i]];
             
         }
         int res = 0;
         for(int i = 0;i <N; i++)
         if(!f[n][i]) res++;
         
         cout << res;
    }
    return 0;
}

一维做法
在这里插入图片描述


#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 10010;

int a[110];
bool f[N];

int gcd(int a, int b)
{
    
    
    return b ? gcd(b, a % b) : a;
}

int main()
{
    
    
    int n;
    scanf("%d", &n);
    int d = 0;
    for (int i = 1; i <= n; i ++ )
    {
    
    
        scanf("%d", &a[i]);
        d = gcd(d, a[i]);
    }

    if (d != 1) puts("INF");
    else
    {
    
    
        f[0] = true;
        for (int i = 1; i <= n; i ++ )
            for (int j = a[i]; j < N; j ++ )
                f[j] |= f[j - a[i]];

        int res = 0;
        for (int i = 0; i < N; i ++ )
            if (!f[i])
                res ++ ;

        printf("%d\n", res);
    }

    return 0;
}


7. 括号配对

Acwing1070. 括号配对
在这里插入图片描述
输入样例:

[])

输出样例:

1

在这里插入图片描述

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

const int N = 110, inf = 0x3f3f3f3f;

char s[N];
int f[N][N]; // f[i][j]代表将i~j个字符变成GBE的所有方案的集合的最小值

bool check(int a, int b)
{
    
    
    if (s[a] == '[' && s[b] == ']' || s[a] == '(' && s[b] ==')') return true;
    return false;
}

int main()
{
    
    
    scanf("%s", s + 1);
    int n = strlen(s + 1);

    for (int len = 1; len <= n; len++)
        for (int l = 1; l + len - 1 <= n; l++)//循环左右端点
        {
    
    
            int r = l + len - 1;
            if (len == 1) f[l][r] = 1;
            else
            {
    
    
                f[l][r] = inf;
                if (check(l, r)) f[l][r] = min(f[l][r], f[l + 1][r - 1]);//左右匹配
                for (int k = l; k <= r; k++)
                    f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r]);
            }
        }

    cout << f[1][n] << endl;

    return 0;
}

8. 旅游规划

1078. 旅游规划
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 200010, M = N*2;
int n, h[N],e[M],ne[M],idx,d1[N],d2[N],p1[N],up[N];
int maxd;
void add(int a,int b)
{
    
    
    e[idx] = b;
    ne[idx] = h[a];
    h[a] = idx++;
}

void dfs_d(int u, int father)
{
    
    
    for(int i = h[u]; i != -1;i = ne[i])
    {
    
    
        int j =e[i];
        if(j != father)
        {
    
    
            dfs_d(j,u);
        int dist = d1[j]+1;
        if(dist > d1[u])
        {
    
    
            d2[u] = d1[u],d1[u] = dist;
            p1[u] = j;
        }
        else if(dist > d2[u]) d2[u] = dist;
        }
    }
    maxd = max(maxd,d1[u]+d2[u]);
}

void dfs_u(int u,int father)
{
    
    
    for(int i = h[u]; i != -1; i = ne[i])
    {
    
    
        int j = e[i];
        if(j != father)
        {
    
    
            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()
{
    
    
    cin >>n;
    memset(h,-1,sizeof h);
    for(int i = 0;i <n - 1; i++)
    {
    
    
        int a, b;
        cin >> 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) cout << i << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Annabel_CM/article/details/113591255
今日推荐