zoukankan      html  css  js  c++  java
  • “玲珑杯”ACM比赛 Round #18 A 前缀预处理 D dp

    DESCRIPTION

    今天HHHH 考完了期末考试,他在教学楼里闲逛,他看着教学楼里一间间的教室,于是开始思考:

    如果从一个坐标为 (x1,y1,z1)(x1,y1,z1) 的教室走到(x2,y2,z2)(x2,y2,z2) 的距离为 |x1x2|+|y1y2|+|z1z2||x1−x2|+|y1−y2|+|z1−z2|

    那么有多少对教室之间的距离是不超过RR 的呢?

    INPUT
    第一行是一个整数T(1T10)T(1≤T≤10) , 表示有TT 组数据 接下来是TT 组数据,对于每组数据: 第一行是两个整数n,q(1n5×104,1q103)n,q(1≤n≤5×104,1≤q≤103) , 表示有nn 间教室, qq 次询问. 接下来是nn 行, 每行3个整数xi,yi,zi(0xi,yi,zi10)xi,yi,zi(0≤xi,yi,zi≤10) ,表示这间教室的坐标. 最后是qq 行,每行一个整数R(0R109)R(0≤R≤109) ,意思见描述.
    OUTPUT
    对于每个询问RR 输出一行一个整数,表示有多少对教室满足题目所述的距离关系.
    SAMPLE INPUT
    1 3 3 0 0 0 1 1 1 1 1 1 1 2 3
    SAMPLE OUTPUT
    1 1 3
    HINT
    对于样例,1号教室和2号教室之间的距离为3, 1号和3号之间的距离为3, 2号和3号之间的距离为0
    SOLUTION
    题解:考虑到坐标的范围非常小,我们可以统计每一个点有多少个教室,然后枚举坐标预处理答案,然后做一个前缀和即可

    要小心的是R的范围  注意乘的时候会爆int

     1 #pragma comment(linker, "/STACK:102400000,102400000")
     2 #include <cstdio>
     3 #include <iostream>
     4 #include <cstdlib>
     5 #include <cstring>
     6 #include <algorithm>
     7 #include <cmath>
     8 #include <cctype>
     9 #include <map>
    10 #include <set>
    11 #include <queue>
    12 #include <bitset>
    13 #include <string>
    14 #include <complex>
    15 #define ll long long
    16 using namespace std;
    17 int t;
    18 int n,q;
    19 int mp[15][15][15];
    20 int x[50004],y[50004],z[50004];
    21 int s[50004];
    22 ll sum[505];
    23 int main()
    24 {
    25     scanf("%d",&t);
    26     for(int i=1;i<=t;i++)
    27     {
    28         for(int j=0;j<=10;j++)
    29             for(int l=0;l<=10;l++)
    30              for(int k=0;k<=10;k++)
    31                mp[j][l][k]=0;
    32         for(int j=0;j<=50;j++)
    33             sum[j]=0;
    34         scanf("%d %d",&n,&q);
    35         int jishu=0;
    36         for(int j=1;j<=n;j++)
    37         {
    38             scanf("%d %d %d",&x[j],&y[j],&z[j]);
    39             if(mp[x[j]][y[j]][z[j]]==0)
    40                 s[jishu++]=j;
    41             mp[x[j]][y[j]][z[j]]++;
    42       }
    43         for(int j=0;j<jishu;j++)
    44         {
    45             for(int k=j;k<jishu;k++)
    46             {
    47                 if(j==k)
    48                 {
    49                     ll now=mp[x[s[j]]][y[s[j]]][z[s[j]]];
    50                     sum[0]+=now*(now-1)/2;
    51                 }
    52                 else{ 
    53  int dis=abs(x[s[j]]-x[s[k]])+abs(y[s[j]]-y[s[k]])+abs(z[s[j]]-z[s[k]]);
    54   sum[dis]+=mp[x[s[k]]][y[s[k]]][z[s[k]]]*mp[x[s[j]]][y[s[j]]][z[s[j]]];
    55                 }
    56             }
    57         }
    58         for(int j=1;j<=50;j++)
    59             sum[j]+=sum[j-1];
    60         int exm;
    61         for(int j=1;j<=q;j++)
    62         {
    63             scanf("%d",&exm);
    64             if(exm>50)
    65                 printf("%lld
    ",sum[50]);
    66             else
    67                 printf("%lld
    ",sum[exm]);
    68         }
    69     }
    70     return 0;
    71 }
    DESCRIPTION

    今天HHHH 在操场上跑步,HHHH 作为一个爱运动的人,肯定会想方设法把跑步所消耗的能量减到最少.

    现在这个操场上有nn 个可以休息的点,他们的坐标分别为x1,x2...xn(xixi+1)x1,x2...xn(xi≤xi+1) ,HHHH 刚开始在 x1x1 ,并且他只能在这些点休息,在中途不能停下来,否则会因为旁边的音浪太强而被晃到.

    如果HHHH 连续跑一段长度为ll 的距离,那么他将会消耗2l+a2l+a 的能量(aa 为HHHH 的可爱值)

    现在给你这些点的坐标,请帮HHHH 计算他跑到xnxn 点所需要消耗的能量最少是多少.

    INPUT
    第一行是一个整数T(1T10)T(1≤T≤10) ,表示有TT 组数据 对于每组数据输入一行2个整数n,a (1n105,1a106)n,a (1≤n≤105,1≤a≤106) 表示总共有nn 个休息点,HHHH 的可爱值为aa . 接着一行nn 个数x1,x2...,xn(0xi3×106,0xi+1xi30)x1,x2...,xn(0≤xi≤3×106,0≤xi+1−xi≤30) ,表示点的位置.
    OUTPUT
    每组数据输出一行,一个整数,表示最小需要花费的体力
    SAMPLE INPUT
    2 3 2 3 5 7 3 10 3 5 7
    SAMPLE OUTPUT
    12 26
    HINT
    对于第一组样例,最少的体力消耗是先从3跑到5,消耗6点体力,再从5跑到7,消耗6点体力,共12点 对于第二组样例,最少的体力消耗是直接从3跑到7,消耗26点体力.
    题解:

    首先我们可以想到一个简单的dp方程

    dp[i]=min(dp[j]+2^(dis[i]dis[j]))+a

    1.然后我们发现这个2^x很快就会比a 高到不知道哪里去,所以当这个距离超过一定值的时候肯定是分开

    跑比较划算了,所以我们只需要枚举当前点前面的几十个点再转移一下就行了

    2.我们也可以简单的推导一下发现这个dp方程是决策性单调的所以你懂的

     1 #pragma comment(linker, "/STACK:102400000,102400000")
     2 #include <cstdio>
     3 #include <iostream>
     4 #include <cstdlib>
     5 #include <cstring>
     6 #include <algorithm>
     7 #include <cmath>
     8 #include <cctype>
     9 #include <map>
    10 #include <set>
    11 #include <queue>
    12 #include <bitset>
    13 #include <string>
    14 #include <complex>
    15 #define ll long long
    16 using namespace std;
    17 int t;
    18 int aa[100005];
    19 int b[100005];
    20 ll dp[3000006];
    21 map<int,int>mp;
    22 int n,a;
    23 int main()
    24 {
    25     scanf("%d",&t);
    26     int ans=0;
    27     for(int j=1;j<=t;j++)
    28     {
    29         scanf("%d %d",&n,&a);
    30         int jishu=0;
    31         mp.clear();
    32         for(int i=1;i<=n;i++){
    33             scanf("%d",&aa[i]);
    34             if(mp[aa[i]]==0){
    35                 b[jishu++]=aa[i];
    36                 mp[aa[i]]=1;
    37             }
    38             }
    39         sort(b,b+jishu);
    40         for(int i=0;i<jishu;i++){
    41             dp[i]=1e18+1;
    42             }
    43         dp[0]=0;
    44         for(int i=1;i<jishu;i++)
    45         {
    46             for(int j=i-1;j>=0;j--)
    47             {
    48                 if(b[i]-b[j]>30)
    49                     break;
    50                 dp[i]=min(dp[i],dp[j]+(1ll<<(b[i]-b[j]))+a);
    51             }
    52         }
    53         printf("%lld
    ",dp[jishu-1]);
    54     }
    55     return 0;
    56 }
  • 相关阅读:
    01、启动优先和安全设置
    5、bam格式转为bigwig格式
    1、蛋白质二级结构预测方法
    12、IGV-Integrative Genomics Viewer
    docker-compose 工具安装
    docker-compose.yml 语法说明
    docker 镜像和容器的批量清理
    rancher 笔记 之 rancher应用中心
    golang 学习笔记
    docker registry 搭建
  • 原文地址:https://www.cnblogs.com/hsd-/p/7184079.html
Copyright © 2011-2022 走看看