zoukankan      html  css  js  c++  java
  • 田忌赛马

    洛咕

    题意:两个人各有n匹马,给出每匹马的速度,n场比赛中,问第一个人最多能赢多少场.(n<=2000)

    分析:其实就是跟田忌赛马的贪心策略差不多:如果我速度最大的马能赢对面速度最大的马,肯定用.如果我速度最小的马能赢对面速度最小的马,也肯定用.否则就用我速度最小的马去消耗掉对面速度最大的马.

    根据这个贪心策略我们有两种实现方式,一是直接按照贪心策略来模拟.

    把两方的马都从小到大排序,然后模拟n场比赛的情况即可.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=2005;
    int a[N],b[N];
    int main(){
    	int n=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1;i<=n;++i)b[i]=read();
    	sort(a+1,a+n+1);sort(b+1,b+n+1);
    	int i1=1,i2=1,j1=n,j2=n,ans=0;
    	for(int i=1;i<=n;++i){
    		if(a[j1]>b[j2])++ans,--j1,--j2;//最大的能赢
    		else if(a[j1]<b[j2])--ans,++i1,--j2;//最大的不能赢,就拿最小的去消耗
    		else if(a[i1]>b[i2])++ans,++i1,++i2;//最小的能赢,这一句放这里或者放下面都可以
    		else{
    //最大的打成平局的话,还是拿最小的去消耗,但是可能到了最后,我最小的与对面最大的也打成了平局
    			if(a[i1]<b[j2])--ans;//这里一定要有这个判断
    			++i1;--j2;
    		}
    	}
    	printf("%d
    ",ans*200);
        return 0;
    }
    

    另一种方法是转换成DP来实现.设(g[i][j])表示我的第i匹马与对方第j匹马比赛是否能赢(赢为1,平局为0,输为-1),(f[i][j])表示前i场比赛中,我出了j(第1到j)匹好马,i-j(第i-j到n)匹劣马的最大收益.

    (f[i][j]=max(f[i-1][j]+g[n-(i-j)+1][i],f[i-1][j-1]+g[j][i]))

    为了方便,我们规定对面的出马顺序是从强到弱.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=2005;
    int a[N],b[N],f[N][N],g[N][N];
    int main(){
    	int n=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1;i<=n;++i)b[i]=read();
    	sort(a+1,a+n+1);reverse(a+1,a+n+1);
    	sort(b+1,b+n+1);reverse(b+1,b+n+1);
    	for(int i=1;i<=n;++i)
    		for(int j=1;j<=n;++j){
    			if(a[i]>b[j])g[i][j]=1;
    			if(a[i]==b[j])g[i][j]=0;
    			if(a[i]<b[j])g[i][j]=-1;
    			f[i][j]=-1e9;
    		}
    	for(int i=1;i<=n;++i){
    		f[i][0]=f[i-1][0]+g[n-i+1][i];
    		f[i][i]=f[i-1][i-1]+g[i][i];
    		for(int j=1;j<i;++j){
    			f[i][j]=max(f[i-1][j]+g[n-(i-j)+1][i],f[i-1][j-1]+g[j][i]);
    		}
    	}
    	int ans=0;
    	for(int i=0;i<=n;++i)ans=max(ans,f[n][i]);
    	printf("%d
    ",ans*200);
        return 0;
    }
    
  • 相关阅读:
    对象数组输出学生信息
    对象数组实现添加和显示客户信息
    控制台输出模拟注册登录幸运抽奖
    对象数组和for循环遍历输出学生的信息
    控制台输出<迷你DVD管理>
    CF524B 题解
    优先队列的重载运算符
    [洛谷日报第19期]Codeforces游玩攻略(转)
    最短路(三种基础算法)
    P2032 扫描
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11542369.html
Copyright © 2011-2022 走看看