zoukankan      html  css  js  c++  java
  • NOIP模拟题——B

    【题目描述】
    我们要从n种食物选m个出来,安排一个顺序吃掉它(们),每种食物有个美味值ai,然后我们有k个规则,每个规则有 xi, yi 和 ci三个数,如果吃完第xi种食物接下来马上吃第yi种食物,第j种食物的美味值会增加ci。每种食物至多吃一个,求美味值最大的和是多少?
    【输入格式】
    第一行有三个数n,m,k,k代表有k个规则(0<=k<=n*(n-1))。
    第二行有n个数字代表每个食物的美味值。
    接下去有k行,每行三个数xi,yi,ci。保证没有任意两个规则的xi和yi同时相同。
    【输出格式】
    一行一个数代表答案
    【sample input1】
    2 2 1
    1 1
    2 1 1
    【sample output1】
    3
    【sample input 2】
    4 3 2
    1 2 3 4
    2 1 5
    3 4 2
    【sample output 2】
    12
    【数据范围】
    30% m<=n<=5 ,0<=ci,ai<=1e5
    100% m<=n<=18,0<=ci,ai<=1e9

    由于数据小,找的多,所以考虑状压DP。f[i][j]表示i状态时最后一个数为j的最大值,若没有吃完则每次找还未吃掉的和吃掉的(看做是当前状态最后一个吃掉的),若吃多了就continue,否则(找完m个了)找dp[i][j]的最大值。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cmath>
     5 using namespace std;
     6 const long long maxn=20;
     7 long long dp[(1<<maxn)][maxn];
     8 long long v[maxn];
     9 long long pp[maxn][maxn];
    10 long long n,m,k;
    11 long long max(long long x,long long y)
    12 {
    13     if(x<y)return y;
    14     return x;
    15 }
    16 long long _count(long long x)
    17 {
    18     long long an=0;
    19     while(x)
    20     {            
    21         if(x&1)an++;
    22         x>>=1;
    23     }
    24     return an;
    25 }
    26 int main()
    27 {
    28     freopen("b.in","r",stdin);
    29     freopen("b.out","w",stdout);
    30     scanf("%I64d%I64d%I64d",&n,&m,&k);
    31     for(int i=0;i<=n-1;i++)
    32     scanf("%I64d",&v[i]);
    33     for(int i=1;i<=k;i++)
    34     {
    35         int x,y;long long z;
    36         scanf("%d%d%I64d",&x,&y,&z);
    37         pp[x-1][y-1]=z;
    38     }
    39     long long ans=0;
    40     for(int i=0;i<=n-1;i++)
    41     dp[(1<<i)][i]=v[i];
    42     for(int i=0;i<(1<<n);i++)
    43     {
    44         int qw=_count(i);
    45         if(qw>m)continue;
    46         if(qw==m)
    47         {
    48             for(int j=0;j<=n-1;j++)
    49             ans=max(ans,dp[i][j]);
    50             continue;        
    51         }
    52         else
    53         {
    54             for(int j=0;j<=n-1;j++)//枚举没有吃的
    55             {
    56                 if(((1<<j)&i)==0)//没有吃
    57                 {
    58                     for(int k=0;k<=n-1;k++)//枚举最后吃的点
    59                     if(((1<<k)&i))//吃过 
    60                     dp[i|(1<<j)][j]=max(dp[i][k]+pp[k][j]+v[j],dp[i|(1<<j)][j]);
    61                 } 
    62             }
    63             
    64         }
    65     }
    66     printf("%I64d",ans);
    67     return 0;
    68 }
  • 相关阅读:
    html中的a标签
    dl,dt,dd标签的使用
    MySQL innodb中各种SQL语句加锁分析
    Js字符串与十六进制的相互转换 【转】
    亿级Web系统搭建:单机到分布式集群【转】
    pm2 设置开机启动
    spring cloud 项目相关集成简介
    spring boot下JedisCluster方式连接Redis集群的配置
    并发编程 – Concurrent 用户指南--转
    JDBC 事务和 JTA 事务
  • 原文地址:https://www.cnblogs.com/937337156Zhang/p/6051322.html
Copyright © 2011-2022 走看看