从这周开始开始了第一次训练。。。差距太明显了。。。半看题解半自己打。。。贪心还是很好理解的,就是想不到而已。。。想不到而已。。
第一题
hdu1257
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1257
最少拦截系统
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 35600 Accepted Submission(s): 14083
怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.
8 389 207 155 300 299 170 158 65
2
这个题首先联想到了以前做过的拦截导弹的题,记忆中是用的DP。。。可是突然看到叶神发的用最长上升子序列不对。。。于是转移方向,对着贪心使劲。
首先说明贪心的方法:每一个导弹都是用已有的最大高度最小切大于他的系统,有点绕口。就是找一个能打他的然后距离它最小的一个系统。如果没有系统能够打他,就设置一个新系统。那么为什么这样做呢?我们知道,导弹依次过来,假设前面已经有能够打到这个导弹的系统,那么使用这个系统和新建一个系统效果是一样的,都是把目前的最大高度降到这个导弹的高度。所以,如果有能用的系统,肯定没必要新建系统。那么选择高度最小的是因为能打的高度越大这个系统的潜力越大,所以选择高度小的系统。那么代码如下:
#include<stdio.h>
int main()
{
int n,h[100001],d[100001],cnt,i,j,min,remin;
while (scanf("%d",&n)!=EOF)
{
for (i=1;i<=n;i++) scanf("%d",&h[i]);
cnt=0;
for (i=0;i<=100001;i++) d[i]=0;
for (i=1;i<=n;i++)
{
min=30000; remin=-1;
for (j=1;j<=cnt;j++)
{
if ((h[i]<=d[j])&&(d[j]<min))
{
min=d[j];
remin=j;
}
}
if (remin!=-1)
{
d[remin]=h[i];
}
else
{
cnt++;
d[cnt]=h[i];
}
}
printf("%d\n",cnt);
}
return 0;
}
是的,还学到了一种读入方式。不告诉数据组数的读入
这个题卡了挺久的,原因在于我竟然一开始没看到题目里说有多组数据!!!!这种ZZ的错误……
好吧第二题
hdu4550
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4550
卡片游戏
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 2011 Accepted Submission(s): 622
首先取最上方的卡片放到桌子上,然后每次取最上方的卡片,放到桌子上已有卡片序列的最右边或者最左边。当N张卡片全部都放到桌子上后,桌子上的N张卡片构成了一个数。这个数不能有前导0,也就是说最左边的卡片上的数字不能是0。游戏的目标是使这个数最小。
现在你的任务是帮小明写段程序,求出这个最小数。
然后下面有T行, 每行是一个只含有0~9的字符串,表示N张叠在一起的卡片,最左边的数字表示最上方的卡片。
[Technical Specification]
T<=1000
1 <= N <= 100
3 565 9876543210 9876105432
556 1234567890 1678905432
贪心啊贪心!
这个题怎么贪心呢。。。
显然如果想要数整体最小,那小的一定要往前放,大的一定是往后放。可是问题来了,不能有前导零。
我已经忘记当天晚上做到两点半的思路了……说明看题解记忆确实不深刻。。。我也忘记了被哪里卡到了两点半。。。
那就写一下今天的吧
也是参照了某一位大牛的题解,发现了一个很优化的解法。
想要数整体最小,那第一位一定是除零外的最小的数。
而且
是最靠后的。
当找到最靠后的最小的数后,这个数以后的所有数都要往右边补
在此之前,依然是贪心的思想,如果比现有的第一个数大,补右边,否则补左边,并更新第一个数。
还想说一点特别机智的做法!num数组开到了300,从中间开始设l,r,一个往左走就是加前面,一个往右走就是加后面,最后在l,r之间输出!
太机智了!
省去了字符串的操作……
#include<stdio.h>
#include<string.h>
int main()
{
int n,i,po,min,head,t,l,r,len;
char s[110];
int num[301];
scanf("%d",&n);
while (n-->0)
{
memset(s,0,sizeof(s));
memset(num,0,sizeof(num));
min=10;//找最小值
head=10;//记录首位
scanf("%s",s);
len=strlen(s);
for (i=0;i<len;i++) //找最小的数的过程
{
t=s[i]-'0';
if (t<=min&&t!=0)
{
min=t;
po=i;//po用来记录最小数的位置
}
}
l=150; r=150;
for (i=0;i<len;i++)
{
t=s[i]-'0';
if (i<po)//在到达位置之前
{
if (t>head)
{
num[++r]=t;//如果这个数大于头,就加后面
}
else
{
num[l--]=t;//否则加前面
head=t;//更新头
}
}
else
if (i==po)//到达位置
{
num[l--]=t;//放前面
head=t;
}
else//超过位置
num[++r]=t;//放后面
}
for (i=l+1;i<=r;i++) printf("%d",num[i]);
printf("\n");
}
}
不得不说真的好机智啊!TAT
第三题!!!现在已经一点十分了。。。明天还有高数啊!
hdu1052
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1052
Tian Ji -- The Horse Racing
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 27476 Accepted Submission(s): 8172
"That was about 2300 years ago. General Tian Ji was a high official in the country Qi. He likes to play horse racing with the king and others."
"Both of Tian and the king have three horses in different classes, namely, regular, plus, and super. The rule is to have three rounds in a match; each of the horses must be used in one round. The winner of a single round takes two hundred silver dollars from the loser."
"Being the most powerful man in the country, the king has so nice horses that in each class his horse is better than Tian's. As a result, each time the king takes six hundred silver dollars from Tian."
"Tian Ji was not happy about that, until he met Sun Bin, one of the most famous generals in Chinese history. Using a little trick due to Sun, Tian Ji brought home two hundred silver dollars and such a grace in the next match."
"It was a rather simple trick. Using his regular class horse race against the super class from the king, they will certainly lose that round. But then his plus beat the king's regular, and his super beat the king's plus. What a simple trick. And how do you think of Tian Ji, the high ranked official in China?"
![](https://i-blog.csdnimg.cn/blog_migrate/6fa9aa2f0590001c7074c427f5048537.gif)
Were Tian Ji lives in nowadays, he will certainly laugh at himself. Even more, were he sitting in the ACM contest right now, he may discover that the horse racing problem can be simply viewed as finding the maximum matching in a bipartite graph. Draw Tian's horses on one side, and the king's horses on the other. Whenever one of Tian's horses can beat one from the king, we draw an edge between them, meaning we wish to establish this pair. Then, the problem of winning as many rounds as possible is just to find the maximum matching in this graph. If there are ties, the problem becomes more complicated, he needs to assign weights 0, 1, or -1 to all the possible edges, and find a maximum weighted perfect matching...
However, the horse racing problem is a very special case of bipartite matching. The graph is decided by the speed of the horses --- a vertex of higher speed always beat a vertex of lower speed. In this case, the weighted bipartite matching algorithm is a too advanced tool to deal with the problem.
In this problem, you are asked to write a program to solve this special case of matching problem.
3 92 83 71 95 87 74 2 20 20 20 20 2 20 19 22 18 0
200 0 0
这个题。。。感觉看了题解很容易就是自己想不到啊。。。。
贪心过程是这样的:
田忌最慢的马(记为tjtail)是不是比国王最慢的马(记为kingtail)快
如果是:赢一局
如果不是:
tjtail是不是小于kingtail
如果是:用tj最慢的碰king最快的,输一局
如果不是:那么tjtail=kingtail
田忌最快的(记为tjhead)是不是比国王最快的(记为kinghead)快
是:赢一局
不是:
tjhead是不是小于kinghead
是:tjtail碰kinghead,输一局
不是:说明田忌最快的等于国王最快的
是不是tjtail小于kinghead
是:tjtail碰kinghead
不是:肯定不可能大,所以只能是一样快,说明田忌和国王剩下所有的马一样快了,不用比了就。。。
贴代码:
#include<stdio.h>
int main()
{
int i,n,tjhead,tjtail,kinghead,kingtail,ans=0;
int tj[1001],king[1001];
void quicksort(int a[],int l,int r);
while (scanf("%d",&n),n!=0)
{
ans=0;
for (i=1;i<=n;i++) scanf("%d",&tj[i]);
for (i=1;i<=n;i++) scanf("%d",&king[i]);
quicksort(tj,1,n);
quicksort(king,1,n);
tjhead=n; tjtail=1;
kinghead=n; kingtail=1;
for (i=1;i<=n;i++)
{
if (tj[tjtail]>king[kingtail])
{
ans++;
tjtail++;
kingtail++;
}
else
if (tj[tjtail]<king[kingtail])
{
ans--;
tjtail++;
kinghead--;
}
else
{
if (tj[tjhead]>king[kinghead])
{
ans++;
tjhead--;
kinghead--;
}
else
if (tj[tjhead]<king[kinghead])
{
ans--;
tjtail++;
kinghead--;
}
else
{
if (tj[tjtail]<king[kinghead])
{
ans--;
tjtail++;
kinghead--;
}
else
{
break;
}
}
}
}
printf("%d\n",ans*200);
}
return 0;
}
void quicksort(int a[],int l,int r)
{
int i,j,base,t;
i=l; j=r;
base=a[(l+r)/2];
while (i<=j)
{
while (a[i]<base) i++;
while (base<a[j]) j--;
if (i<=j)
{
t=a[i]; a[i]=a[j]; a[j]=t;
i++; j--;
}
}
if (l<j) quicksort(a,l,j);
if (i<r) quicksort(a,i,r);
}
不行不行。。。必须睡觉了。。懒得注释了。。。
加油加油!还有很多东西需要学。
希望能独立自主的做出一个贪心
还好明天思修不上了。
晚安。。
哦对了,今天去了老年公寓做志愿,情况一般,和预想有差距。
晚安!