Advertisement

上海计算机学会2022年11月月赛C++乙组T3菜单设计

阅读量:

菜单设计

内存限制: 256 Mb 时间限制: 1000 ms

题目描述

小爱需要从 n 道菜中,选出 m 道菜作为餐厅的菜单。已知第 i 道菜的美味值为 xi​。还有 p 种加分规则,第 i 条规则包含三个参数 ai​ 、bi​ 和 ci​,表示在第 ai​ 道菜后,如果下一道菜是 bi​ 道,会有额外 ci​ 点美味值。

如何设计菜单,才能使美味值到达最大。

输入格式

输入第一行,两个正整数n,m
输入第二行,𝑛n个正整数,x1​,...,xn​
输入第三行,一个正整数,p
​接下来p行,每行3个正整数,分别表示第i条建议的三个参数ai​,bi​,ci​

输出格式

输出一个正整数,表示所选菜单能获得的最大美味值。

数据范围
  • 对于 50% 数据,1≤m≤n≤8;
  • 对于 100% 数据,1≤m≤n≤18;
    0≤xi​,ci​≤10^9,1≤ai​,bi​≤n ,1≤p≤n×(n−1) 。

数据保证没有两条菜品建议的ai​和bi​完全相同

样例数据

输入:
4 3
2 5 1 3
2
2 1 6
4 3 1
输出:
16
说明:
按第2道、第1道、第4道备选菜肴的顺序组成正式菜单
获得 2+5+3=10 点美味值,外加第2道后接第1道备选菜肴所带来的 6 点额外美味值
故最大美味值为 16

解析:状态压缩DP(动态规划)

详见代码:

复制代码
 #include <bits/stdc++.h>

    
 using namespace std;
    
 const long long maxn = 20;
    
 long long dp[(1 << maxn)][maxn];
    
 long long v[maxn];
    
 long long pp[maxn][maxn];
    
 long long n, m, k;
    
 long long max(long long x, long long y) {
    
     if(x < y)return y;
    
     return x;
    
 }
    
 long long _count(long long x) {
    
     long long an = 0;
    
     while(x) {
    
     if(x & 1)an++;
    
     x >>= 1;
    
     }
    
     return an;
    
 }
    
 int main() {
    
     scanf("%lld%lld", &n, &m);
    
     for(int i = 0; i <= n - 1; i++) {
    
     scanf("%lld", &v[i]);
    
     }
    
     scanf("%lld", &k);
    
     for(int i = 1; i <= k; i++) {
    
     int x, y;
    
     long long z;
    
     cin >> x >> y >> z;
    
     pp[x - 1][y - 1] = z;
    
     }
    
     long long ans = 0;
    
     for(int i = 0; i <= n - 1; i++)
    
     dp[(1 << i)][i] = v[i];
    
     for(int i = 1; i < (1 << n); i++) {
    
     int qw = _count(i);
    
     if(qw > m)continue;
    
     if(qw == m) {
    
         for(int j = 0; j <= n - 1; j++)
    
             ans = max(ans, dp[i][j]);
    
         continue;
    
     } else {
    
         for(int j = 0; j <= n - 1; j++) { //枚举没有吃的
    
             if(((1 << j)&i) == 0) { //没有吃
    
                 for(int k = 0; k <= n - 1; k++) //枚举最后吃的点
    
                     if(((1 << k)&i)) //吃过
    
                         dp[i | (1 << j)][j] = max(dp[i][k] + pp[k][j] + v[j], dp[i | (1 << j)][j]);
    
             }
    
         }
    
     }
    
     }
    
     printf("%lld", ans);
    
     return 0;
    
 }
    
    
    
    
    AI写代码cpp
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-05-31/CGZkcjISlyKgHfeuDiLmdr90YQxU.png)

全部评论 (0)

还没有任何评论哟~