动态规划|P1650 田忌赛马[普及+提高】DP

田忌赛马 - 洛谷
首先对大王的进行从高到低排序,也顺便对田忌进行排序。如果田忌头部马能够战胜本局大王马,那么就出队,否则选择最末尾的马,那么每局也就有两种情况,选择末尾马,选择头部马。dp[i][j]代表第i轮时,田忌前面出了j匹马。他可以本轮出第j匹马,也可以i-1轮出到j匹马,本轮出第min(n,n-(i-j)+1)的马。【因为为了凑够i匹,必须从最后选出剩余的】
第一轮时, dp[1][1] dp[1][0](最后一匹马)分别处理
第二轮dp[2][1] 依靠dp[1][1]与dp[1][0]来转移 ,也就是说,两局头选一马,可以第一局选,第二局选。 dp[2][2]依靠dp[1][1]来转移dp[2][0]依靠dp[1][0]来转移,符合比赛规则与顺序。
同理,第三轮 dp[3][1]依靠dp[2][1],dp[2][0]转移,三局选一马,可以第三局选,可以第一局,第二局选,但都包含在dp[2][1]之内
里面其实蕴含了贪心的思想,也就是本局大王的马能怼掉就必须用当前最牛的马怼掉,否则用最差的马送掉。那万一我们能怼的时候放弃这一局呢,显然当前最牛的马会去抢夺次牛马的生意,做出的贡献仍然是一局。但剩余的马如果无法怼掉这一局的大王马,就不如先用最强的怼掉,那万一次强的也能怼掉本局大王马呢,那么最强与次强其实是等价的,他们都能怼掉剩余的马,用哪个都一样。

#include # includeusing namespace std; typedef long long int ll; int dp[2010][2010]; int a[2010],b[2010]; int c[2010][2010]; bool cmp(int a,int b) { return a>b; } int main() {int n; cin>>n; for(int i=1; i<=n; i++) cin>>a[i]; for(int i=1; i<=n; i++) cin>>b[i]; sort(a+1,a+1+n,cmp); sort(b+1,b+1+n,cmp); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { if(a[i]>b[j]) c[i][j]=1; else if(a[i]
【动态规划|P1650 田忌赛马[普及+提高】DP】

    推荐阅读