acm周末学习总结

这周主要把精力放到了贪心算法上,在vjudge上做了好几道题,基本上体会到了贪心的奥妙之处。即每次选择子结构的最优解,每次都是最好的选择,贪心贪心,不贪怎么能行。

基本策略是对性价比进行排序,每次选择当前性价比最高的,也可以直接选择当前的最大的或最小的进行操作。比如有道纸牌转移问题,就是比较平均值和当前纸牌堆的纸牌数,先把每堆纸牌数都通过转移变成平均值,再逐步完成。做了几道题,越发感觉到算法的精妙,ac的快乐。还是得多刷题,多想多思考

均分纸牌(NOIP2002)
        有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。
        移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。
        现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。例如 N=4,4 堆纸牌数分别为:  ① 9 ② 8 ③ 17 ④ 6
        移动3次可达到目的:
        从 ③ 取4张牌放到④(9 8 13 10)->从③取3张牌放到 ②(9 11 10 10)-> 从②取1张牌放到①(10 10 10 10)。
【输入格式】
       N(N 堆纸牌,1 <= N <= 100) 
       A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000)
【输出格式】
       所有堆均达到相等时的最少移动次数。
【样例输入】Playcard.in
    4
    9 8 17 6 
【样例输出】Playcard.out
    3

伪码

       cin>>n;
  ave=0;step=0; 
  for (i=1;i<=n;++i)
   {
    cin>>a[i]; ave+=a[i];              //读入各堆牌张数,求总张数ave
   } 
  ave/=n;                                          //求牌的平均张数ave
  for (i=1;i<=n;++i) a[i]-=ave;         //每堆牌的张数减去平均数
  i=1;j=n;
  while (a[i]==0&&i<n) ++i;            //过滤左边的0
  while (a[j]==0&&j>1) --j;              //过滤右边的0
  while (i<j)
   {
   a[i+1]+=a[i];                              //将第i堆牌移到第i+1堆中去
   a[i]=0;                                        //第i堆牌移走后变为0
   ++step;                                      //移牌步数计数 
   ++i;                                            //对下一堆牌进行循环操作
   while (a[i]==0&&i<j) ++i;          //过滤移牌过程中产生的0
   } 
  cout<<step<<endl; 

Lindsay is a shopaholic. Whenever there is a discount of the kind where you can buy three items and only pay for two, she goes completely mad and feels a need to buy all items in the store. You have given up on curing her for this disease, but try to limit its effect on her wallet.

You have realized that the stores coming with these offers are quite selective when it comes to which items you get for free; it is always the cheapest ones. As an example, when your friend comes to the counter with seven items, costing 400, 350, 300, 250, 200, 150, and 100 dollars, she will have to pay 1500 dollars. In this case she got a discount of 250 dollars. You realize that if she goes to the counter three times, she might get a bigger discount. E.g. if she goes with the items that costs 400, 300 and 250, she will get a discount of 250 the first round. The next round she brings the item that costs 150 giving no extra discount, but the third round she takes the last items that costs 350, 200 and 100 giving a discount of an additional 100 dollars, adding up to a total discount of 350.

Your job is to find the maximum discount Lindsay can get.

Input
The first line of input gives the number of test scenarios, 1 <= t <= 20. Each scenario consists of two lines of input. The first gives the number of items Lindsay is buying, 1 <= n <= 20000. The next line gives the prices of these items, 1 <= pi <= 20000.

Output
For each scenario, output one line giving the maximum discount Lindsay can get by selectively choosing which items she brings to the counter at the same time.

Sample Input
1
6
400 100 200 350 300 250

Sample Output
400

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a[20010];
int cmp(int a,int b)
{
    return a>b;
}
int main()
{
    int n,x,sum=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        for(int i=1;i<=x;i++)
        {
            cin>>a[i];
        }
        sort(a+1,a+x+1,cmp);
        for(int i=1;i<=x;i++)
        {
            if(i%3==0) sum+=a[i];
        }
        cout<<sum<<endl;
        sum=0;
    }
        return 0;
}

这道题就是排个序就ok了

猜你喜欢

转载自blog.csdn.net/weixin_43238423/article/details/88606944