zoukankan      html  css  js  c++  java
  • 考试


    啊拖了好久了~
    今天来填个坑


    T1

    地震

    描述

    一场地震毁了Farmer John的整个农场。他是个有恒心的人,决定重建农场。在重建了所有n(1<=n<=400)块田野后,他意识到还得修路将它们连起来。完工后,任两个田野间必须有路。
    研究了地形后,FJ认为m(1<=m<=10000)条双向的道路可能建造。由于资金短缺,他希望已尽可能省钱的方式完成整个工程。
    幸运的是,奶牛们已经成立了针对地震后修建农场道路的工程顾问公司。奶牛们也很有经济头脑,对没有漂亮利润的工作从不感兴趣。
    奶牛们关心可能的利益。他们已经说定了为修路所获的酬金f(1<=f<=2,000,000,000),并得到一张关于可能的道路、修建每条路的时间(以小时计)(1<=t<=2,000,000,000)以及花费(1<=c<=2000,000,000)的列表。在两块田野间可能有多于一条的道路被列出,所给数据总有可以连通所有田野的修路方案,虽然可能无利可图。
    确定奶牛修路最高的盈利率。

    输入

    第一行三个整数N, M, F。
    2...M+1行: 每行四个空格隔开的整数: i, j, c,t描述两块田夜间的一条道路。

    输出

    只包含一个数,保留四位小数,奶牛每个小时可以得到的最大利润,如果利润非正,输出0.0000 。

    样例

    quake.in
    5 5 100
    1 2 20 5
    1 3 20 5
    1 4 20 5
    1 5 20 5
    2 3 23 1
    quake.out
    1.0625
    
    *奶牛选择建最后四条路,总花费83时间16,他们的筹劳是100,所以他们在16各单位时间内得到利润100-83:17/16 = 1.0625。
    

    和最小生成树有点像
    不如叫它平均最小生成树
    题目要求的是 $ frac { F- sum c_i }{ sum t_i } = $最大值 $ ans $,
    通过瞎移可得到 $ sum t_i imes ans = F - sum c_i $
    二分ans,把边权设成 $ c_i + t_i imes ans $,跑最小生成树就好了。
    代码蒯上

    #include<iostream>
    #include<iomanip>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    inline int gotcha()
    {
        register int _a=0;bool _b=1;register char _c=getchar();
        while(_c<'0' || _c>'9'){if(_c=='-')_b=0;_c=getchar();}
        while(_c>='0' && _c<='9')_a=_a*10+_c-48,_c=getchar();
        return _b?_a:-_a;
    }
    const int _ = 402,__ = 10002;
    struct edge
    {
    	int to,fr,len,tim;double co;
    	edge(){to=fr=len=tim=co=0;}
    	const bool operator < (const edge &b)const{return co<b.co;}
    }e[__];
    int ecnt=0;
    void add(int fr,int to,int len,int tim)
    {e[++ecnt].to=to,e[ecnt].len=len,e[ecnt].fr=fr,e[ecnt].tim=tim;}
    int fa[_],n,m,got;
    int finder(int a){return a!=fa[a]?fa[a]=finder(fa[a]):a;}
    void link(int a,int b){fa[finder(a)]=finder(b);}
    bool kruskal(double tar)
    {
    	register int i,j=1;register double s=got;
    	for(i=1;i<=ecnt;i++)e[i].co=tar*e[i].tim+e[i].len,printf("%d %lf
    ",i,e[i].co);
    	sort(e+1,e+ecnt+1);
    	for(i=1;i<=n;i++)fa[i]=i;
    	for(i=1;i<=m;i++)
    	{
    		if(finder(e[i].fr)!=finder(e[i].to))
    		{
    			link(e[i].fr,e[i].to);
    			s-=e[i].co;
    			if(s<0)return 0;
    		}
    	}
    	return 1;
    }
    int main()
    {
    	register int i,j,k,a,b;register double l=0,r=1e29;
    	n=gotcha(),m=gotcha(),got=gotcha();
    	for(i=1;i<=m;i++)
    	{
    		j=gotcha(),k=gotcha(),a=gotcha(),b=gotcha();
    		add(j,k,a,b);
    	}
    	if(!kruskal(0)){puts("0.0000");return 0;}
    	while(fabs(l-r)>=1e-13)
    	{
    		double mid=(l+r)/2;
    		if(kruskal(mid))l=mid;
    		else r=mid;
    		cerr<<l<<" "<<r<<endl;
    	}
    	printf("%.4lf",l);
    	return 0;
    }
    

    T2

    http://www.lydsy.com/JudgeOnline/problem.php?id=1816 .

    扑克牌

    描述

    你有n种牌,第i种牌的数目为ci。另外有一种特殊的牌:joker,它的数目是m。你可以用每种牌各一张来组成一套牌,也可以用一张joker和除了某一种牌以外的其他牌各一张组成1套牌。比如,当n=3时,一共有4种合法的套牌:{1,2,3}, {J,2,3}, {1,J,3}, {1,2,J}。
    给出n, m和ci,你的任务是组成尽量多的套牌。每张牌最多只能用在一副套牌里(可以有牌不使用)。

    输入

    第一行包含两个整数n, m,即牌的种数和joker的个数。第二行包含n个整数ci,即每种牌的张数。

    输出

    输出仅一个整数,即最多组成的套牌数目。

    样例

    cards.in
    3 4
    1 2 3
    cards.out
    3
    

    解释

    输入数据表明:一共有1个1,2个2,3个3,4个joker。最多可以组成三副套牌:{1,J,3}, {J,2,3}, {J,2,3},joker还剩一个,其余牌全部用完。

    数据范围

    50%的数据满足:2<=n<=5, 0<=m<=106, 0<=ci<=200
    100%的数据满足:2<=n<=50, 0<=m, ci<=500,000,000。


    一道二分。
    二分答案ans,要加的joker的数量就是 $ sum max(mid-cnt[i],0) $.
    要判断是否超出了拥有的joker数量。
    代码蒯上

    #include<iostream>
    #include<iomanip>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    inline int gotcha()
    {
        register int _a=0;bool _b=1;register char _c=getchar();
        while(_c<'0' || _c>'9'){if(_c=='-')_b=0;_c=getchar();}
        while(_c>='0' && _c<='9')_a=_a*10+_c-48,_c=getchar();
        return _b?_a:-_a;
    }
    const int _ = 52;
    int cnt[_],n,m;
    bool finder(int a)
    {
    	register int i,j=min(a,m);
    	for(i=1;i<=n;i++){if(cnt[i]<a)j-=a-cnt[i];if(j<0)return 0;}return 1;
    }
    int main()
    {
    	register int i,mid,l=0,r=2e9;
    	n=gotcha(),m=gotcha();
    	for(i=1;i<=n;i++)cnt[i]=gotcha();
    	while(r>l){mid=(l+r+1)>>1;if(finder(mid))l=mid;else r=mid-1;}
    	printf("%d",l);
    	return 0;
    }
    

    T3

    https://www.luogu.org/problem/show?pid=3199#sub .

    请使用死八法判负环的方法来作这一题
    二分答案 $ ans $ ,在死八法的时候把每一条边权都减掉 $ ans $ ,
    如果找到了负环就说明 $ ans $ 大了,反之 $ ans $ 小了。
    最后 $ ans $ 的值就是最小圈的平均边权值了

    代码蒯上

    #include<iostream>
    #include<iomanip>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    inline int gotcha()
    {
    	register int _a=0;bool _b=1;register char _c=getchar();
    	while(_c<'0' || _c>'9'){if(_c=='-')_b=0;_c=getchar();}
    	while(_c>='0' && _c<='9')_a=_a*10+_c-48,_c=getchar();
    	return _b?_a:-_a;
    }
    const int _ = 3002, __ = 10002;
    struct edge{int to,ne,len;edge(){to=ne=len=0;}}e[__];
    int he[_]={0},ecnt=0;
    void add(int fr,int to,int len)
    {e[++ecnt].to=to,e[ecnt].len=len,e[ecnt].ne=he[fr],he[fr]=ecnt;}
    int n,m;
    double dis[_],mid;
    bool ed[_],vict;
    void spfa(int d)
    {
    	if(vict)return;
    	ed[d]=1;int i,a;
    	for(i=he[d];i;i=e[i].ne)
    	{
    		a=e[i].to;if(dis[a]>dis[d]+e[i].len-mid)
    		{dis[a]=dis[d]+e[i].len-mid;if(ed[a]){vict=1;return;}spfa(a);}
    	}
    	ed[d]=0;
    }
    bool check()
    {
    	memset(dis,0,sizeof(dis)),memset(ed,0,sizeof(ed)),vict=0;
    	for(int i=1;i<=n;i++){spfa(i);if(vict)return 1;}return 0;
    }
    int main()
    {
    	register int i,j,k,a;
    	register double l=-1e33,r=1e33;
    	n=gotcha(),m=gotcha();
    	for(i=1;i<=m;i++)j=gotcha(),k=gotcha(),a=gotcha(),add(j,k,a);
    	while(l+1e-10<r){mid=(l+r)/2;if(check())r=mid;else l=mid;}
    	printf("%.8lf",l);
    	return 0;
    }
    

  • 相关阅读:
    REST framework框架的基本组件
    GIT如何根据历史记录回退代码
    如何查看磁盘存储空间
    git免密拉取代码
    windows好用的cmd命令
    git如何新建分支
    screen命令
    解决windows配置visual studio code调试golang环境问题
    转载一篇棒棒的AWK教程
    解决Creating Server TCP listening socket 54.179.160.162:7001: bind: Cannot assign requested address
  • 原文地址:https://www.cnblogs.com/finder-iot/p/7635914.html
Copyright © 2011-2022 走看看