您的位置:首页 > 其它

2016.10.28第一次训练贪心专题——第一弹

2016-10-31 00:49 225 查看
从这周开始开始了第一次训练。。。差距太明显了。。。半看题解半自己打。。。贪心还是很好理解的,就是想不到而已。。。想不到而已。。

第一题

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


Problem Description

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能超过前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹.

怎么办呢?多搞几套系统呗!你说说倒蛮容易,成本呢?成本是个大问题啊.所以俺就到这里来求救了,请帮助计算一下最少需要多少套拦截系统.

 

Input

输入若干组数据.每组数据包括:导弹总个数(正整数),导弹依此飞来的高度(雷达给出的高度数据是不大于30000的正整数,用空格分隔)

 

Output

对应每组数据输出拦截所有导弹最少要配备多少套这种导弹拦截系统.

 

Sample Input

8 389 207 155 300 299 170 158 65

 

Sample Output

2

 

Source

浙江工业大学第四届大学生程序设计竞赛

这个题首先联想到了以前做过的拦截导弹的题,记忆中是用的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


Problem Description

  小明最近宅在家里无聊,于是他发明了一种有趣的游戏,游戏道具是N张叠在一起的卡片,每张卡片上都有一个数字,数字的范围是0~9,游戏规则如下:

  首先取最上方的卡片放到桌子上,然后每次取最上方的卡片,放到桌子上已有卡片序列的最右边或者最左边。当N张卡片全部都放到桌子上后,桌子上的N张卡片构成了一个数。这个数不能有前导0,也就是说最左边的卡片上的数字不能是0。游戏的目标是使这个数最小。

  现在你的任务是帮小明写段程序,求出这个最小数。

 

Input

第一行是一个数T,表示有T组测试数据;

然后下面有T行, 每行是一个只含有0~9的字符串,表示N张叠在一起的卡片,最左边的数字表示最上方的卡片。

[Technical Specification]

T<=1000

1 <= N <= 100

 

Output

对于每组测试数据,请在一行内输出能得到的最小数。

 

Sample Input

3
565
9876543210
9876105432

 

Sample Output

556
1234567890
1678905432

 

Source

2013金山西山居创意游戏程序挑战赛——初赛(2)

贪心啊贪心!

这个题怎么贪心呢。。。

显然如果想要数整体最小,那小的一定要往前放,大的一定是往后放。可是问题来了,不能有前导零。

我已经忘记当天晚上做到两点半的思路了……说明看题解记忆确实不深刻。。。我也忘记了被哪里卡到了两点半。。。

那就写一下今天的吧

也是参照了某一位大牛的题解,发现了一个很优化的解法。

想要数整体最小,那第一位一定是除零外的最小的数。

而且

是最靠后的。

当找到最靠后的最小的数后,这个数以后的所有数都要往右边补

在此之前,依然是贪心的思想,如果比现有的第一个数大,补右边,否则补左边,并更新第一个数。

还想说一点特别机智的做法!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


Problem Description

Here is a famous story in Chinese history.

"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?"



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.

 

Input

The input consists of up to 50 test cases. Each case starts with a positive integer n (n <= 1000) on the first line, which is the number of horses on each side. The next n integers on the second line are the speeds of Tian’s horses. Then the next n integers
on the third line are the speeds of the king’s horses. The input ends with a line that has a single 0 after the last test case.

 

Output

For each input case, output a line containing a single number, which is the maximum money Tian Ji will get, in silver dollars.

 

Sample Input

3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0

 

Sample Output

200
0
0

 

Source

2004 Asia Regional Shanghai

这个题。。。感觉看了题解很容易就是自己想不到啊。。。。

贪心过程是这样的:

田忌最慢的马(记为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);
}


不行不行。。。必须睡觉了。。懒得注释了。。。

加油加油!还有很多东西需要学。

希望能独立自主的做出一个贪心

还好明天思修不上了。

晚安。。

哦对了,今天去了老年公寓做志愿,情况一般,和预想有差距。

晚安!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息