贪心思维 专题记录 2017-7-21

A、UVa 10382 - Watering Grass

题目大意:

有一块草坪,长为l,宽为w,在它的水平中心线上有n个位置可以安装喷水装置,各个位置上的喷水装置的覆盖范围为以它们自己的半径ri为圆。求出最少需要的喷水装置个数。

思路 :转化一下 将二维降成一维      d = sqrt(1.0*r*r-w*w/4.0) 接着就是区间覆盖问题了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10000+10;
typedef pair <int,int > pii;
typedef pair <double ,double >pdd;

struct p{
    double a,b;
};

int n;
double l,w;
pdd s[maxn];

bool cmp(const pii &x,const pii &y)
{
    if(x.first != y.first)
        return x.first < y.first;
    return x.second < y.second;
}

int solve()
{
    int cnt = 0;
    double last = 0,far = 0;
    for(int i=0;i < n;i++)
    {
        if(last >= l) return cnt;
        if(s[i].first <= last)
            far = max(far,s[i].second);
        else if(s[i].first > last)
        {
            cnt++;
            last = far;
            if(s[i].first <= last)
                far = max(far,s[i].second);
            else
                return -1;
        }
    }
    if(last < l && far >= l) return cnt+1;
    if(far < l ) return -1;
    return cnt;
}

int main ()
{
    while( scanf("%d%lf%lf", &n, &l, &w) != EOF)
    {
        for(int i=0;i < n;i++)
        {
            double pos , r;
            scanf("%lf %lf",&pos,&r);
            double d = sqrt(1.0*r*r-w*w/4.0);
            s[i].first = pos - d, s[i].second = pos + d;
        }
        sort(s,s+n,cmp);
        cout<< solve()<<endl;
    }
    return 0;
}

A

B、UVa 10905 - Children‘s Game

题目大意:

给出n个数字 输出组合最大的

思路 :两个数 如果位数相同 直接比较大小 ;

       如果不同 就两个数换位置 看哪个大;

#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
using namespace std;

string s[60];

bool cmp(const string &a,const string &b){
    if(a.size() == b.size()){
        return a < b;
    }
    string t1 = a+b, t2=b+a;
    return t1 < t2;
}

int main()
{
    int n;
    while (cin >> n && n)
    {
        for(int i=0;i<n;i++)
            cin >> s[i];
        sort(s,s+n,cmp);

        for(int i=n-1;i>=0;i--)
            cout<< s[i];
        cout<<endl;
    }
    return 0;
}

B

C、UVA 11134 Fabled Rooks

题目大意:

  在一个n*n(1<=n<=5000)的棋盘上放置n个车,每个车都只能在给定的一个矩形里放置,使其n个车两两不在同一行和同一列,判断并给出解决方案

思路 :把题目里的二维的改成一维的,就是有一行,让你放,每个车可以放一个区间[li,ri],让你找一种方案,使得每个车不在同一个格子里。然后就可以这样贪心:枚举每个格子,记为i,那么是不是所有满足左端点li <= i的里头,挑一个右端点尽可能小的来放在这一个格子里面?,因为右端点越大,它后面可 能可以放的格子越多,越小,可放的格子越小,所以我们这样贪心的来放

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 5000 + 10;
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef pair <int ,int > pii;
typedef pair <LL ,LL >pLL;
typedef unsigned long long ull;
struct node {
    int left,ri,order;
    bool operator < (const node & l)const{
        if(left != l.left) return left < l.left;
        return ri < l.ri;
    }
} x[maxn],y[maxn];

int X[maxn],Y[maxn];

bool solve (int n,node s[],int S[])
{
    sort(s,s+n);
    priority_queue <pii,vector<pii>,greater<pii> > q;
    int cnt =0, ret = 0;
    for(int i=1;i <= n;i++)
    {
        while (cnt < n && s[cnt].left <= i)//不停找左边界
        {
            q.push( pii(s[cnt].ri,s[cnt].order) );//右边的边界 压进来
            cnt++;
        }
        if(q.size() == 0) return 0;

        pii p =q.top();
        if(p.first < i) return 0; //右边界如果小于i的话 已经找不到了

        S[p.second] = i;
        q.pop();
        ret++;
      //  cout << ret <<endl;
    }
    return ret == n;
}

int main ()
{
    int n;
    while (~scanf("%d",&n) && n)
    {
        for(int i=0;i < n;i++)
        {
            scanf("%d%d%d%d",&x[i].left, &y[i].left , &x[i].ri, &y[i].ri);
            x[i].order = y[i].order = i;
        }
        if( solve (n,x,X) && solve (n,y,Y) )
        {
            for(int i=0; i < n;i++)
            {
                printf("%d %d\n",X[i],Y[i]);
            }
        }
        else
            printf("IMPOSSIBLE\n");
    }
    return 0;
}

C

D、uva 11100 - The Trip

题目大意:

  有很多包,已知包的区别只在于高度不一样,小包可以装到大包里边,求最终剩下多少个包,并输出没一个组合

思路 :相同的包裹没办法在一个组里面  所以最后剩下的包 即为最大的 相同的包的 个数 k;

    然后按照大小排序,然后每隔k个间隔选一个数  构成一个组别  example:x,x+k,.....x+t*k (x+t*k <= n)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10000+10;
int s[maxn];
int num[1000010];

int main ()
{
    int n;
    while (cin >> n && n){
        int k = 0;
        memset(num,0,sizeof(num));
        for(int i=0;i<n;i++){
            cin >> s[i];
            num[s[i]] ++;
            k = max(k,num[s[i]]);
        }
        cout<< k <<endl;
        sort(s,s+n);
        for(int i=0;i<k;i++)
        {
            cout<< s[i];
            for(int j=k+i;j<n;j+=k){
                cout<< " "<<s[j];
            }
            cout<< endl;
        }
        //cout<<endl;
    }
    return 0;
}

D

E、UVa 11384 - Help is needed for Dexter

题目大意:

给你1~n,n个连续的整数,每次可以从里面取出人一个数字减去一个任意数,  问最少操作多少次可以全变成0。

思路 : 本题思路就是每次都找中间的那个 然后直接减掉 比如 1 2 3 4 5  就找 3 然后剪掉3 就变成 1 2 0 1 2

    然后 接着就变成了 1 2  依次递减

#include <bits/stdc++.h>
using namespace std;

int main ()
{
    int n;
    while (cin >> n)
    {
        int cnt = 0;
        while (n > 0 )
        {
            n/=2;
            cnt++;
        }
        cout<<cnt<<endl;
    }
    return 0;
}

E

F、UVa 10795 A Different Task

题目大意:

有三个柱子  然后给你初始 和 目标的盘子所在的柱子  求最小移动次数

思路 :

参照 http://www.cnblogs.com/arbitrary/archive/2012/12/11/2813245.html

就是 首先找最大不在目标柱子上的盘子K 之前已经就位了 不用动

然后  转换成   一个大概的状态: 只有K 在 初始盘  然后 其余的k-1个都在中转盘上   然后 想把K 移动到 除了第三个盘上

所以问题变成答案=从初始局面移到参考局面步数+目标局面移到参考局面步数+1;

#include <iostream>
#include <cstring>
#include <string.h>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;
const int mod = 1e9 + 7;
const int maxn = 70;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
typedef pair<int, int>pii;
typedef pair<double, double>pdd;
typedef long long LL;
typedef unsigned long long ull;
int s[maxn],e[maxn];

LL f(int *p,int i,int final)
{
    if ( i == 0) return 0;
    if(p[i] == final) return f(p,i-1,final);
    return f(p,i-1,6-final-p[i]) + (1LL << (i-1));//将i-1个盘子 从中转柱子 移动到本来的位置 所以加上2的i-1次方
}

int main()
{
    int n;
    int Case =1;
    while (~scanf("%d",&n), n)  // 有n个盘子
    {
        for(int i=1;i<=n;i++)
            cin >> s[i];
        for(int i=1;i<=n;i++)
            cin >> e[i];
        int k = n;
        while(s[k] == e[k] && k) k--;
        LL ans = 0;
        if( k != 0)
        {
            int other = 6-s[k] - e[k];//找到中转的柱子

            ans = f(s,k-1,other) + f(e,k-1,other) + 1;//把1到k-1移到中转柱子上 然后再将k移动到目标柱子
        }
        printf("Case %d: %lld\n",Case++,ans);
    }
    return 0;
}

F

G、UVA 11520 - Fill the Square

题目大意:

给你一个n*n的格子,有些里面有大写字母,用大写字母填满格子,相邻的格子中字母不相同, 并且使得从上到下,从左到右的字母字典序最小。

思路 : 构造。将格子从上到下,从左到右编号,然后按编号填充,避免冲突即可,这样一定最小。

(如果,该方案不是最小,那么之前一定会选择更小的方案,而不是本方案)

#include <iostream>
#include <cstring>
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 15;
char s[maxn][maxn];

int main ()
{
    int t,n;
    cin >> t;  //100 * 100 *26
    for(int a=1;a<=t;a++)
    {
        cin >> n;
        for(int i=0;i<n;i++) cin >> s[i];
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(s[i][j] == ‘.‘)
                {
                    for(char k = ‘A‘;k<=‘Z‘;k++)
                    {
                        bool ok = 1;
                        if(i > 0 && s[i-1][j] == k) ok=0;
                        if(i < n-1 &&s[i+1][j] == k ) ok=0;
                        if(j > 0 && s[i][j-1] == k) ok=0;
                        if(j< n-1 && s[i][j+1] == k) ok = 0;
                        if( ok )
                        {
                            s[i][j] = k;
                            break;
                        }
                    }

                }
            }
        }
        printf("Case %d:\n",a);
        for(int b=0;b<n;b++)
            cout<< s[b]<<endl;
    }
    return 0;
}

G

时间: 2024-10-09 09:29:09

贪心思维 专题记录 2017-7-21的相关文章

[题解]线段树专题测试2017.1.21

很单纯的一道线段树题.稍微改一下pushDown()就行了. Code(线段树模板竟然没超100行) 1 #include<iostream> 2 #include<sstream> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<cctype> 8 #include<queue> 9

codeforce 985C Liebig&#39;s Barrels(贪心+思维)

Liebig's Barrels time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You have m?=?n·k wooden staves. The i-th stave has length ai. You have to assemble n barrels consisting of k staves each, y

贪心/思维题 Codeforces Round #310 (Div. 2) C. Case of Matryoshkas

题目传送门 1 /* 2 题意:套娃娃,可以套一个单独的娃娃,或者把最后面的娃娃取出,最后使得0-1-2-...-(n-1),问最少要几步 3 贪心/思维题:娃娃的状态:取出+套上(2),套上(1), 已套上(0),先从1开始找到已经套好的娃娃层数, 4 其他是2次操作,还要减去k-1个娃娃是只要套上就可以 5 详细解释:http://blog.csdn.net/firstlucker/article/details/46671251 6 */ 7 #include <cstdio> 8 #i

hdu 4898 LCP+贪心思维

题意:将一个字符串切成k块,使得字典序最大的那块最小. ORZ  WJMZBMR,几行题解读了一天才懂. 快速比较两个子串的大小可以利用LCP(最长公共前缀),比较公共前缀的下一个字符的大小就够了. 利用这种思想,首先我们可以预处理所有子串的LCP(后缀数组+记录 O(2nlog(2n))+O(n*n),dp(O(4*n*n))) 然后将这些子串利用LCP按照字典序排序,开始二分答案. 二分的答案就是这K个块字典序的上限.假设以i作为起点,由于字典序上限已知,所以我们可以立刻求出i点最远能选到哪

2017.1.21总结

---恢复内容开始--- 今天写了2道题,一道p1227 一道p1919 p1227原题: 给出一有向图,图中每条边都被标上了关系运算符'<','>','='.现在要给图中每个顶点标上一个大于等于0,小于等于k的某个整数使所有边上的符号得到满足.若存在这样的k,则求最小的k,若任何k都无法满足则输出NO. 例如下表中最小的k为2. 结点1>结点2结点2>结点3结点2>结点4结点3=结点4 如果存在这样的k,输出最小的k值:否则输出'NO'. 这道题是差分约束+拓扑排序题目,需

2017/1/21 上午活动

2017/1/21 上午       from高嘉怡 用开源飞控套件做一架Mini四轴飞行器 http://www.chuangkoo.com/project/48 材料清单 1.MWC飞控)*1                    82元/件 https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-2963753174.64.yQPiw8&id=18839984356 2.720空心杯电机  黑白线*4     5.5元/个 红蓝线*4

Codeforces Round #546 (Div. 2) D 贪心 + 思维

https://codeforces.com/contest/1136/problem/D 贪心 + 思维 题意 你面前有一个队列,加上你有n个人(n<=3e5),有m(m<=个交换法则,假如u在v相邻前面,那么u和v可以交换位置,问你是队列最后一个人的时候你最前可以换到前面哪里 题解 因为相邻才能换,所以最后一个换到前面一定是一步一步向前走,所以不存在还要向后走的情况 设最后一个为u,假设前面有一个能和u换位置的集合,那么需要将这些点尽量往后移动去接u 假设前面有一个不能和u换位置的集合S,

hdu 4550 贪心 思维题 不错

http://acm.hdu.edu.cn/showproblem.php?pid=4550 想了挺久,然后各种分类 终于AC,如果是现场,对自己没信心的话,估计还是要WA,,,,,,然后搜题解,发现人家都认为是简单题,看来我还是太弱了,牡丹江没有做出来K看来还是自己贪心和思维有问题 d是一个Deque 最朴素的算法是,如果当前的数<=d.front(),那么插入队列的前面,否则插入队列后面,但是有零所以需要单独处理,还是自己多举例找规律 我的策略: 1.记录0的个数zero,最小非零的数的个数

2017.7.21夏令营清北学堂解题报告

预计分数: 60+30+0=90=划水 实际分数: 90+30+20=140=rank5=雷蛇鼠标 一句话总结:今天该买彩票! T1: 题目描述 从前有一个?行?列的网格. 现在有?种颜色,第?种颜色可以涂??格,保证 Σ? ?? = ? * ?. 需要你对这个网格图进行着色,你必须按照从上到下,每一行内从左到右 的顺序进行着色,并且在用完一种颜色前你不能换颜色(当然颜色的使用顺序 是随意的). 每个相邻的相同色块可以获得1分,问在给定的规则下进行着色所能获得的 最高分是多少. 多组数据. 输入