题意:
田忌和国王赛马,每人有n匹马,胜得200,负得-200,平得0;现在要求安排两人的出马顺序,使得田忌得到的钱最多。
题解:
1)dp
最开始想用贪心,但后来发现在有很多相等速度马的情况下,很难贪心出来。所以需要用dp。
dp[i][j]表示打了i场比赛,用了j匹慢马(从最慢的开始用)和i-j匹快马(从最快的开始用)时的最优成绩。
原理:也算是一种变着法的贪心把。我们将国王的马从大到小排序,我们要么用最好的马战胜掉,要么用最差的马顶掉。
若不用最差的马还是输了,那最差的马还是要输给别的马,当然用最差的马好;若没有输,那用好马战胜和用这匹马战胜的效果相同,剩下的那匹肯定比国王剩下的马都强。
若不用最好的马去战斗,若不能战胜那肯定不用说是费的;若能战胜,那么肯定也能战胜国王剩余的马,保留这匹马和保留最好的马的效果一样。
dp[i][j]=max(dp[i-1][j]+judge(n-i+j,i-1),dp[i-1][j-1]+judge(j-1,i-1));
2)贪心
在学了dp方法之后,又学了贪心的思想。
将田忌和国王的马都从大到小排序,执行以下步骤
//下面说的最快和最慢都是在经过上次操作后剩下的马。
①每次将田忌剩余马中最快的马和国王剩余马忠最快的马比较,若赢就跳到②,输跳到③,平跳到④。直到所有马都比完为止
②田忌用剩余最快的马战胜国王剩余的最快的马,(即使田忌有别的马能战胜国王最快的马,那用别的马和最快的马效果一样,因为剩下的另一匹马还是都大于国王剩下的马)回到①
③田忌用最慢的马顶掉国王最快的马(物尽其用,反正对国王最快的马怎么都要输,那就用最慢的马好了),回到①
④比较田忌最慢的马和国王最慢的马,若田忌的马胜跳到⑤,负跳到⑥,平跳到⑦
⑤用田忌最慢的马战胜国王最慢的马(没有平局的情况下的贪心,也是物尽其用),跳回①
⑥用田忌最慢的马顶掉国王最快的马(反正田忌最慢的马都要输,那就把国王最快的马顶掉好了,也是物尽其用),跳回①
⑦用田忌最慢的马顶掉国王最快的马(这是难点,主要的问题就出在这里。如果每次遇到平的话都对调,那么最终在这些马上的得等最高只有0分;如果顶掉的话,那么田忌最快的马也肯定可以战胜国王最慢的马,那样可以保证最低0分,在出现田忌【1,2,3】和国王【1,2,3】的情况下,最高分数就不是0分了,所以贪心时选择用田忌最慢的马顶掉国王最快的马),跳回①
代码:
1.dp
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1e3+10;
int dp[maxn][maxn];//dp[i][j],打了i场,用了j匹慢马
int a[maxn],b[maxn];
int judge(int i,int j)
{
if(a[i]>b[j])return 1;
else if(a[i]y;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
if(n==0)break;
int i,j,k;
for(i=0;ib[i-1])dp[i][0]=dp[i-1][0]+1;
else if(a[n-i]b[i-1])dp[i][i]=dp[i-1][i-1]+1;
else if(a[i-1]
2.贪心
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1e3+10;
int a[maxn],b[maxn];
int cmp(int x,int y)
{
return x>y;
}
int judge(int i,int j)
{
if(i==j)return 0;
else if(i>j)return 1;
else return -1;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
if(n==0)break;
int i,j,k,l,r;
for(i=0;ib[l]){ans++;i++;l++;}
else
{
while(a[j]>b[r]){ans++;j--;r--;}
ans+=judge(a[j],b[l]);
j--;
l++;
}
}
printf("%d\n",ans*200);
}
return 0;
}