数学与简单DP

1. 买不到的数目

ACWing1205. 买不到的数目
在这里插入图片描述
输入样例:

4 7

输出样例:

17

在这里插入图片描述

参考文献:这篇博客

#include<iostream>
using namespace std;
int main()
{
    
    
    int p,q;
    cin >> p >> q;
    cout << (p-1)*(q-1)-1 <<endl;
    
    return 0;
}

2.蚂蚁感冒

ACWing1211. 蚂蚁感冒
在这里插入图片描述
在这里插入图片描述
**第一个蚂蚁向右走的情况:**

#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 55;
int n, x[N];
int main()
{
    
    
    cin >>n;
    for(int i = 0; i < n; i++) cin >> x[i];
    int left = 0, right = 0;//分别表示左边向右走的蚂蚁数量,和右边向左走的蚂蚁数量
    
    for(int i = 1; i < n; i++)
     if(abs(x[i]) < abs(x[0]) && x[i] >0) left++;//左边向右走
     else if(abs(x[i]) > abs(x[0]) && x[i] <0) right++;
     
     //第一个蚂蚁向右   right > 0   left + right + 1
     //  right == 0   1
     
     //第一个蚂蚁向左    left > 0   left + right + 1
     // left == 0      1
     
     if(x[0] >0 && right == 0|| x[0] < 0 && left == 0) cout << 1<<endl;
     else cout << left + right + 1 <<endl;
     return 0;
    
}

3. 饮料换购

ACWing1216. 饮料换购
在这里插入图片描述

#include<iostream>
using namespace std;
const int N = 10010;
int cnt;
int main()
{
    
    
    int n;
    cin >>n;
    cnt = n;
    
    while(n >= 3)
    {
    
    
        cnt  += (n)/3;
        n = n/3 + n%3;
    }
    cout << cnt;
    
    return 0;
}

4. 摘花生

ACWing1015. 摘花生
在这里插入图片描述
在这里插入图片描述
思路
状态表示
集合:定义f[i][j]为从(1, 1)到达(i, j)的所有方案
属性:最大值
状态转移
(i, j)从(i-1, j)即上方过来
(i, j)从(i, j-1)即左方过来
空间压缩
f[i][j]只需要用到这一层和上一层的f元素,所以可以压缩成滚动数组。在此之上,还可以直接压缩成一维数组。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 110;
int g[N][N];
int f[N];
int main()
{
    
    
    int n, r,c;
    cin>> n;
    while(n--)
    {
    
    
        cin >> r >> c;
        for(int i = 1; i <= r; i++)
         for(int j = 1; j <= c; j++)
          scanf("%d", &g[i][j]);
          
         for(int i = 1; i <= r; i++)
         for(int j = 1; j <= c; j++)
          f[j] = max(f[j], f[j-1]) + g[i][j];
          
         cout << f[c] <<endl;
         memset(f,0,sizeof f);
    }
    return 0;
}

5.地宫取宝

ACWing1212. 地宫取宝
X 国王有一个地宫宝库,是 n×m 个格子的矩阵,每个格子放一件宝贝,每个宝贝贴着价值标签。

地宫的入口在左上角,出口在右下角。

小明被带到地宫的入口,国王要求他只能向右或向下行走。

走过某个格子时,如果那个格子中的宝贝价值比小明手中任意宝贝价值都大,小明就可以拿起它(当然,也可以不拿)。

当小明走到出口时,如果他手中的宝贝恰好是 k 件,则这些宝贝就可以送给小明。

请你帮小明算一算,在给定的局面下,他有多少种不同的行动方案能获得这 k 件宝贝。

输入格式
第一行 3 个整数,n,m,k,含义见题目描述。

接下来 n 行,每行有 m 个整数 Ci 用来描述宝库矩阵每个格子的宝贝价值。

输出格式
输出一个整数,表示正好取 k 个宝贝的行动方案数。

该数字可能很大,输出它对 1000000007 取模的结果。
在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 55, mod = 1000000007;
int n, m, k;
int w[N][N];
int f[N][N][13][14];//f[i][j][c][k]表示:在(i, j)这个点,拿了c个物品,这些物品中价值最大的是k

int main()
{
    
    
    cin >> n >>m >> k;
    for(int i = 1; i <= n; i++)
     for(int j = 1; j <= m; j++)
     {
    
    
         cin >> w[i][j];
         w[i][j]++;
     }
     //两个边界初始化
    //在起点(1, 1)处
    //如果拿也只能拿a[i][j]这个物品,只有一种方案
    //如果不拿,那就是0个物品,也是一个方案数
    //由于物品价值已经增加了一个偏移量,现在价值的范围是[1, 13]
    //所以价值为0并不代表物品的价值,而是一个边界点
     f[1][1][1][w[1][1]] = 1;//选第一个数
     f[1][1][0][0] = 1;//不选第一个数
     
     for(int i = 1 ; i <= n; i++)
      for(int j = 1; j <= m; j++)
      {
    
    
          if(i == 1 && j == 1) continue;
          for(int u = 0; u <= k; u++)
           for(int v = 0; v <= 13; v++)
           {
    
    
             //不拿物品
               int &val = f[i][j][u][v];
               val = (val + f[i-1][j][u][v])%mod;
               val = (val + f[i][j-1][u][v])%mod;
             //可以拿
               if(u > 0 && v == w[i][j])
               {
    
    
                   for(int c = 0; c <v; c++)
                   {
    
    
                       val = (val +f[i-1][j][u-1][c])%mod;
                       val = (val + f[i][j-1][u-1][c])%mod;
                   }
               }
           }
      }
 //最后把在终点(n, m)处拿c个物品的方案数累加
     int res = 0;
     for(int i = 0; i <= 13; i ++) res = (res + f[n][m][k][i])%mod;
     cout << res <<endl;
     return 0;
}

6.波动数列

Acwing 1214. 波动数列
在这里插入图片描述
输入样例:

4 10 2 3

输出样例:

2

样例解释
两个满足条件的数列分别是2 4 1 3和7 4 1 -2。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1010,mod = 100000007;
int f[N][N];
int get_mod(int a, int b)//求a%b的正整数
{
    
    
    return (a%b+ b)%b;
}
int main()
{
    
    
    int n, s,a,b;
    cin >> n >> s >> a >> b;
    
    f[0][0] = 1;
    for(int i = 1; i < n; i++)//枚举i-1项
     for(int j = 0; j < n; j++)//枚举第i项的n种可能的状态
      f[i][j] = (f[i-1][get_mod(j-a*i,n)]+f[i-1][get_mod(j+b*i,n)])%mod;
      cout << f[n-1][get_mod(s,n)]<<endl;
      return 0;
}

猜你喜欢

转载自blog.csdn.net/Annabel_CM/article/details/113770784