码迷,mamicode.com
首页 > 其他好文 > 详细

【组队赛#9】USACO 2006 January Bronze

时间:2015-04-23 17:39:12      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:acm   比赛题   

 【A题】A. Stump Removal 链接click here~~

【题目大意】一排高低不平的树桩,需要用炸弹全部炸掉,如果一个树桩的前面和后面的树桩高度都比它小,炸弹爆炸的时候会同时炸掉,求尽可能少的放置炸弹的数目,输出树桩的编号

【解题思路】 理解题意,从左往右扫,如果当前位置右边或左边的比它低了或相等,那么就把这个位置炸掉,然后把能炸的都炸掉,判断当前树桩前面的和后面的高度比较,

核心代码

 for(int i=1;i<=n+1;i++)
    {
        if(a[i]>=a[i-1]&&a[i]>=a[i+1])
        cout<<i<<endl;
    }
【F题】F. Dollar Dayz BNU 14323

【题目大意】大数!求解钱币组合问题,坑题一道~~

代码:

/*
Author:HRW
大数!
*/
#include <string>
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1001;
struct bign
{
    int len,s[maxn];
    bign()
    {
        memset(s,0,sizeof(s));
        len = 1;
    }
    bign operator = (const char *num)
    {
        len = strlen(num);
        for(int i=0; i<len; i++)s[i] = num[len-i-1] - '0';
        return *this;
    }
    bign operator = (int num)
    {
        char s[maxn];
        sprintf(s,"%d",num);
        *this = s;
        return *this;
    }
    bign(int num)
    {
        *this = num;
    }
    bign(const char *num)
    {
        *this = num ;
    }
    string str()const
    {
        string res = "";
        for(int i=0; i<len; i++)
            res = (char)(s[i] + '0') + res;
        if (res == "")res = "0";
        return res;
    }
    bign operator + (const bign& b)const
    {
        bign c;
        c.len = 0;
        for(int i=0,g = 0; g|| i<max(len,b.len); i++)
        {
            int x = g;
            if(i<len) x+= s[i];
            if(i<b.len) x+=b.s[i];
            c.s[c.len++] = x%10;
            g = x/10;
        }
        return c;
    }
    void clean()
    {
        while(len > 1 && !s[len-1]) len--;
    }
    bign operator += (const bign& b)
    {
        *this = *this + b;
        return *this;
    }
};
istream& operator >>(istream &in, bign& x)
{
    string s;
    in>>s;
    x = s.c_str();
    return in;
}
ostream& operator << (ostream &out, const bign& x)
{
    out << x.str();
    return out;
}
bign AC[1002];
int main()
{
    int n,k;
    while(cin>>n>>k)
    {
        AC[0] = 1;
        for(int i=1; i<=k; i++)
            for(int j=i; j<=n; j++)
               AC[j]+=AC[j-i];
            cout<<AC[n]<<endl;
    }
    return 0;
}
【E题】E. Redundant Paths BNU14319

【题目大意】给你一个连通的无向图G,至少要添加几条边,才能使其变为双连通图,和POJ 3177一样

【解题思路】一个有桥的连通图要变为双连通图的话,把双连通图收缩为一个点,形成一颗树,需要加的边为(L+1)/2,L为叶子节点个数

ps:BNU竟然加外挂会超时~~orz,以后还是得多注意。。

代码:

/*
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=5010;//点数
const int maxm=20100;//边数,无向
struct Edge
{
    int to,next;
    bool cut;//是否是桥标记
} edge[maxm];
int head[maxn],tot;
int Low[maxn],DFN[maxn],Stack[maxn],Belong[maxn];
int Index,top;
int block;//边双连通块数
bool instack[maxn];
int bridge;//桥的数目
void addedge(int u,int v)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    edge[tot].cut=false;
    head[u]=tot++;
}
void Tarjan(int u,int pre)
{
    int v;
    Low[u]=DFN[u]=++Index;
    Stack[top++]=u;
    instack[u]=true;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].to;
        if(v == pre) continue;
        if(!DFN[v])
        {
            Tarjan(v,u);
            if(Low[u]>Low[v]) Low[u]=Low[v];
            if(Low[v]>DFN[u])
            {
                bridge ++;
                edge[i].cut = true;
                edge[i^1].cut = true;
            }
        }
        else if(instack[v]&&Low[u]>DFN[v])
            Low[u]=DFN[v];
    }
    if(Low[u]==DFN[u])
    {
        block++;
        do
        {
            v=Stack[--top];
            instack[v]=false;
            Belong[v]=block;
        }
        while(v!=u);
    }
}
void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}
int du[maxn];//缩点后形成树,每个点的度数
void solve(int n)
{
    memset(DFN,0,sizeof(DFN));
    memset(instack,false,sizeof(instack));
    Index=top=block=0;
    Tarjan(1,0);
    int res=0;
    memset(du,0,sizeof(du));
    for(int i=1; i<=n; i++)
        for(int j=head[i]; j!=-1; j=edge[j].next)
            if(edge[j].cut) du[Belong[i]]++;
    for(int i=1; i<=block; i++)
        if(du[i]==1)
            res++;//找叶子节点个数为res,构造边双连通图需要加边(res+1)/2
    printf("%d\n",(res+1)/2);
}
int shuru()
{
    int sum=0;
    char ch;
    while((ch=getchar())<='0'||ch>='9');sum=ch-'0';
    while((ch=getchar())>='0'&&ch<='9') sum=sum*10+ch-'0';
    return sum;
}
int main()
{
    //freopen("1.txt","r",stdin);
    int n,m,u,v;
    while(scanf("%d%d",&n,&m)==2)
    {
        init();
        while(m--)
        {
            //scanf("%d%d",&u,&v);
            u=shuru();
            v=shuru();
            addedge(u,v);
            addedge(v,u);
        }
        solve(n);
    }
    return 0;
}



【组队赛#9】USACO 2006 January Bronze

标签:acm   比赛题   

原文地址:http://blog.csdn.net/u013050857/article/details/45216627

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!