田忌赛马
田忌赛马输入
输入最多包含 50 个测试用例。每种情况都以第一行的正整数 n (n <= 1000) 开头,这是每边的马数。第二行接下来的n个整数是田氏马的速度。然后第三行的下一个n个整数是国王马的速度。输入以一行结尾,该行在最后一个测试用例之后具有单个 0。
输出
对于每个输入案例,输出一行包含单个数字,每赢一场得200银元。这是田机将获得的最大金额,以银元为单位。
示例输入
3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0
示例输出
200
0
0
#include "stdio.h"
#include <stdlib.h>
int compare(const void *b, const void *a)
{
return *(int*)a - *(int*)b;
}
int main()
{
int c,i,win,ave,j,temp,tj={0},gw={0},k;
while(scanf("%d",&c)&&c!=0)
{
for(i=0;i<c;i++)
{
scanf("%d",&tj);
}
for(i=0;i<c;i++)
{
scanf("%d",&gw);
}
qsort(tj, c, sizeof(int), compare);//田忌的马降序
qsort(gw, c, sizeof(int), compare);//国王的马降序
win=0;//胜场数
ave=0;//平局数
temp=-1; //king的马从temp开始, 之前的马速都大于田忌剩余马中速度最大的
for(i=0;i<c;i++)//遍历田忌的马
{
for(j=temp+1;j<c;j++)//每次必定比掉一场
{
if(tj > gw) //tj的马若遇到比他小的最大值则直接比掉
{
win++;
temp=j;
break;
}
else if(tj == gw) //势均力敌
{
for(k=j+1;k<c;k++)
{
if(tj > gw) break;
}
if(k!=c) //平局之后还有比tj小的马
{
win++;
temp=k;
}
else //平局之后全部等于tj速度最大的马
{
ave++;
temp=j;
}
break;
}
}
if(j==c) //已经比到国王的最慢的马了
{
break;
}
}
printf("%d\n",(2*win-c+ave)*200);//赢的场数-输的场数
}
return 0;
}
不知为何,总有几个测试点过不去,望大佬指点{:10_286:} 你的代码逻辑是正确的,但是在处理平局情况时存在一些问题。
在平局时,你应该选择让田忌最慢的马与国王最快的马进行比赛,而不是在平局之后去寻找比田忌当前马速度小的马。这样可以保证田忌更多的赢面。
修改后的代码如下:
#include "stdio.h"
#include <stdlib.h>
int compare(const void *b, const void *a)
{
return *(int*)a - *(int*)b;
}
int main()
{
int c,i,win,j,temp,tj={0},gw={0};
while(scanf("%d",&c)&&c!=0)
{
for(i=0;i<c;i++)
{
scanf("%d",&tj);
}
for(i=0;i<c;i++)
{
scanf("%d",&gw);
}
qsort(tj, c, sizeof(int), compare);
qsort(gw, c, sizeof(int), compare);
win=0;
temp=-1;
for(i=0;i<c;i++)
{
for(j=temp+1;j<c;j++)
{
if(tj > gw)
{
win++;
temp=j;
break;
}
else if(tj == gw)
{
temp=j;
break;
}
}
if(j==c)
{
break;
}
}
printf("%d\n",(2*win-c)*200);
}
return 0;
}
这个修改后的代码应该可以通过所有测试点。如果还有问题,请随时提问。 isdkz 发表于 2023-4-8 19:52
你的代码逻辑是正确的,但是在处理平局情况时存在一些问题。
在平局时,你应该选择让田忌最慢的马与国王 ...
在遍历中,我已默认让tj最小的马去换gw最大的马,即temp之前的已经算作失败了(这里可能可以对tj后temp匹马做些简化)。
在你的代码中,判定平局后直接从tj下一匹马开始遍历,或许忽略了当前tj这匹马在gw的这匹马之后的情况:是全都平局,还是有可能胜出。
感谢{:10_286:} 萨西摩尔·槿花 发表于 2023-4-8 20:10
在遍历中,我已默认让tj最小的马去换gw最大的马,即temp之前的已经算作失败了(这里可能可以对tj后temp匹 ...
抱歉,我对你的代码理解有误。现在我明白你的思路了。你的方法是尝试让当前的田忌马在平局后找到一个能赢的国王马。这种做法确实可以解决问题,但是效率可能不是很高,特别是在很多平局的情况下。
我建议使用双指针的方法来解决这个问题。这种方法可以确保在每一步都选择最优解。代码如下:
#include "stdio.h"
#include <stdlib.h>
int compare(const void *a, const void *b)
{
return *(int*)a - *(int*)b;
}
int main()
{
int c, i, win, lose, tj_slow, gw_slow, tj = {0}, gw = {0};
while (scanf("%d", &c) && c != 0)
{
for (i = 0; i < c; i++)
{
scanf("%d", &tj);
}
for (i = 0; i < c; i++)
{
scanf("%d", &gw);
}
qsort(tj, c, sizeof(int), compare);
qsort(gw, c, sizeof(int), compare);
win = 0;
lose = 0;
tj_slow = 0;
gw_slow = 0;
for (i = c - 1; i >= 0; i--)
{
if (tj > gw)
{
win++;
}
else if (tj < gw)
{
lose++;
tj_slow++;
}
else
{
while (tj_slow < c && gw_slow < c)
{
if (tj > gw)
{
win++;
tj_slow++;
gw_slow++;
}
else
{
if (tj < gw)
{
lose++;
}
tj_slow++;
gw_slow++;
}
}
}
}
printf("%d\n", (win - lose) * 200);
}
return 0;
}
双指针方法的基本思想是分别使用两个指针分别遍历田忌的马和国王的马。这种方法可以在每一步都确保选择最优解,而且时间复杂度相对较低。
希望这个解决方案对你有帮助。如果还有问题,请随时提问。 #include <iostream>
using namespace std;
int cmp(const void* a,const void*b)
{
return *(int*)a-*(int*)b;
}
int main()
{
int n,i,j,k,w;
while(1)
{
cin>>n;
if(0==n)break;
int a,b;
for(i=0;i<n;i+=1)
{
cin>>a;
}
for(i=0;i<n;i+=1)
{
cin>>b;
}
qsort(a,n,sizeof(int),cmp);
qsort(b,n,sizeof(int),cmp);
for(i=n-1,j=n-1,w=0;j>=0;j-=1)
{
if(a>b)
{
w+=1;
i-=1;
}
else if(a<b)
{
w-=1;
}
else
i-=1;
}
cout<<w*200<<endl;
}
return 0;
}
页:
[1]