• 集训模拟赛-1-T2


    好了不要在铺垫了直接整吧就

    题目拿来!!!!!!!

    倒水
    (water)
    (256MB,1s)
    【问题描述】
    你有一个水桶(记为 0),两个杯子(记为 1,2)。水桶中的水量
    无限,容量也无限。1 号杯子容量为 a ml,2 号杯子容量为 b ml。一
    开始,两个杯子里都没有水。
    你可以执行以下几种操作:
    1、将 1 号杯子中的水倒入水桶
    2、将水桶中的水倒入 2 号杯子
    3、将 2 号杯子中的水倒入 1 号杯子
    每次倒水直到倒出水的杯子满或倒入水的杯子空才停止。
    现在希望 1 号杯子中的水尽量少,但大于 0。
    问通过以上操作能够获得 1 号杯子的最少水量 t 为多少?(t>0)
    记获得最少水量执行了 pa 次操作 1,pb 次操作 2,希望在最少水量
    的条件下 pa 尽量小(在 pa 相同的情况下还希望 pb 尽量小)。

    【输入格式】
    输入文件名为water.in
    一行,两个数正整数 a b
    【输出格式】
    输出文件名为water.out
    一行,三个数 t pa pb
    (各变量含义如题所述)
    【输入样例】
    water.in water.out
    5 3 1 1 2

    倾倒方案为:
     0->2;
     2->1;
     0->2;
     2->1;
     1->0;
     2->1;
    【数据规模与约定】
    对于 20%的数据,pa,pb 总和不超过 5
    对于 60%的数据,pa<=10^8
    对于 100%的数据,0<b<=a<=10^9

    说实话当时看完这个题我直接套各种东西= =因为一点思路都没有

    但它实际上是个推理题

    首先我们要知道每个操作执行时满足的条件

    1号杯它不会在没有满时倒出,因为1杯未满说明2杯已空(一定有2->1的情况)若倒了就又重新开始了。

    2号杯也只有在空的时候会执行二号操作

    而2->1可以看作一步操作,因为水量是一定的,他们不对1号杯最小水量做出影响

    把1杯2杯步骤三看作一个整体

    杯子容量a+b=x 一开始a,b为空

    到了末期一定是a>=0,b=0

    体现在代码上:

    一号操作:x=x-a

    二号:x=x+b

    三号:x=x

    则求a(min)等于求x(min)

    一号操作Pa次,二号操作Pb次,余下的水s=Pb*b-Pa*a

    余下a与b的线性组合

    x(min)=gcd(a,b)

    s=gcd(a,b)

    且他们的解还要除一个gcd才是min值的累加

    解为-Pa+kb,Pb-ka

    最小为 -Pa+kb/gcd(a,b),Pb-ka/gcd(a,b)

    (好了我知道你们看不懂= =算了,代码一上估计就好理解多了)

    那就代码走起!!!!!!!

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 using namespace std;
     5 int g[71][71];//邻接矩阵 
     6 int f[71][71][71][71];//floyd 
     7 int _Min(int x,int y){return x<y?x:y;}
     8 int main()
     9 {
    10     freopen("travel.in","r",stdin);
    11     freopen("travel.out","w",stdout);
    12     memset(g,63,sizeof(g));
    13     memset(f,63,sizeof(f));
    14     int n,m,T,x,y,k,i,j,l,r,s,t,L;
    15     scanf("%d%d",&n,&m);
    16     for(i=1;i<=m;i++)
    17     {
    18       scanf("%d%d%d",&x,&y,&k);
    19       g[x][y]=_Min(g[x][y],k);//保存邻接矩阵中 
    20     }
    21     for(l=1;l<=n;l++)//f[] 预处理
    22       for(r=l;r<=n;r++)//先枚举 l r
    23       {
    24         for(i=1;i<=n;i++)
    25           for(j=1;j<=n;j++)
    26           {
    27             if(l==r)//只能途经一个点
    28               f[l][r][i][j]=_Min(g[i][j],g[i][l]+g[l][j]);//比较
    29             else
    30               f[l][r][i][j]=_Min(f[l][r-1][i][j],f[l][r-1][i][r]+f[l][r-1][r][j]);//经不经过r 
    31           }
    32       }
    33     scanf("%d",&T);//询问 
    34     while(T--)
    35     {
    36       scanf("%d%d%d",&s,&t,&L);
    37       if(g[s][t]<=L){
    38       printf("-1
    ");//-1为最小的能取到直接出最小答案 
    39       continue;
    40       }
    41       r=1;//分界点右边的节点 恰好小于等于限制条件的那个 
    42       int ans=1<<10; 
    43       for(l=1;l<=n;l++)
    44       {
    45         while(r<=n&&f[l][r][s][t]>L)r++;//对于每一行看看是否需要右移 限制在n之内分界点不出去 
    46         if(r>n)break;
    47         ans=_Min(ans,r-l);//更新答案 
    48       }
    49       if(ans==1<<10)ans=-2;//没有满足条件,直接出-2 
    50       printf("%d
    ",ans);
    51     }
    52     return 0;
    53 }

    o的k?

    奥利给!整他就完了!

    好了今天就到这里吧 如有不懂 我也不会讲= =

    散会!

  • 相关阅读:
    windows 安装mongodb数据库
    shell 编程实战
    利用DNAMAN和clusterx绘制序列比对图片
    json与python对象互转
    python:向mongodb中储存数据
    python中登录mongoDB
    如何绘制漂亮的多序列比对图片
    python爬虫的基本框架
    fastqc
    转录与翻译
  • 原文地址:https://www.cnblogs.com/SKTskyking/p/12293088.html
Copyright © 2020-2023  润新知