zoukankan      html  css  js  c++  java
  • 洛谷 P1650 田忌赛马(dp)

    传送门


    解题思路

    本题从暴力dfs入手,推出dp转移方程。
    先进行排序,速度越大编号越大。
    假设齐王从最大开始的出马,dfs(now,l,r)表示齐王出到编号为now的马,田忌还剩下l-r之间的马(因为田忌一定是要么出最大的马,要么出最小的马)。
    分类讨论,当田忌最大的马大于齐王,则一定拿下这场比赛;
    当田忌最大的小于齐王,则一定演下这场比赛;
    当两者最大的马相等,则两种都有可能,答案取max。
    这样原始代码就出来了:

    int dfs(int now,int l,int r){
    	if(now==0) return 0;
    	if(a[r]>b[now]) return 200+dfs(now-1,l,r-1);
    	if(a[r]<b[now]) return dfs(now-1,l+1,r)-200;
    	return max(dfs(now-1,l,r-1),dfs(now-1,l+1,r)-200);
    }
    

    再加个记忆化或者将其变成for循环,就变成了dp。

    AC代码

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int maxn=2005;
    int n,a[maxn],b[maxn],dp[maxn][maxn];
    template<class T>inline void read(T &x)
    {
        x=0;register char c=getchar();register bool f=0;
        while(!isdigit(c))f^=c=='-',c=getchar();
        while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
        if(f)x=-x;
    }
    int main(){
    	ios::sync_with_stdio(false);
    	read(n);
    	for(int i=1;i<=n;i++) read(a[i]);
    	for(int i=1;i<=n;i++) read(b[i]);
    	sort(a+1,a+n+1);
    	sort(b+1,b+n+1);
    	for(int now=1;now<=n;now++){
    		for(int l=1;l<=n;l++){
    			int r=now+l-1;
    			if(a[r]>b[now]) dp[now][l]=200+dp[now-1][l];
    			else if(a[r]<b[now]) dp[now][l]=dp[now-1][l+1]-200;
    			else dp[now][l]=max(dp[now-1][l],dp[now-1][l+1]-200);	
    		}
    	}
    	cout<<dp[n][1];
        return 0;
    }
    
  • 相关阅读:
    javascript 杂记
    Sublime Text 3 杂记
    Visual Studio命令行工具
    iOS Crash日志
    Cocos引擎开发者指南(1-5)
    Linux防火墙配置(iptables, firewalld)
    jenkins使用git SCM时changelog乱码(Jenkins部署在Linux上,任务在Windows Slave上构建)
    C#枚举类型
    Java 实现大转盘抽奖
    HaspMap和ConcurrentHashMap
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/15338778.html
Copyright © 2011-2022 走看看