usaco 训练总结2

usaco 5.3.1
“怎么做呢?”
“搜呗!”

void dfs(int x,int cnt,int now)
{
    if(cnt>minnum)  
        return ;//剪枝1
    if(now==Q)
    {
        minnum=min(minnum,cnt);
        for(int i=1;i<=cnt;i++)
        {   
            if(ans[i]<b[i])
                return ;
            else if(ans[i]>b[i])
                break; 
        }
        for(int i=1;i<=cnt;i++)
            ans[i]=b[i];
        return ;
    }
    if(x>P)
        return ;
    if(vis[now]<cnt)
        return ;//剪枝2
    vis[now]=cnt;
    dfs(x+1,cnt,now);
    b[++cnt]=a[x];
    for(int j=1;j*a[x]+now<=Q;j++)
        dfs(x+1,cnt,now+j*a[x]);
}

usaco 5.3.3
这是道强连通分量题,如果一堆学校,其中任意一个得到消息其他学校都会得到,那么就把他们缩成一个点,然后看整个图,缩点后有多少个点入度为0,就是传播消息的最小开始数;
至于最小扩展数,在这个缩点后的图,一定只有单向边,而且没有环,所以只要把它补成一棵“树”就好了

#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<stdio.h>'
#include<stack>
#include<vector>
using namespace std;
int n,ru[105]; 
bool vis[105][105];
bool jk[105];
int head[105],next[20050],to[20050],cnt;
int head2[105],next2[20050],to2[20050],cnt2;
void add(int f,int t)
{
    to[++cnt]=t;
    next[cnt]=head[f];
    head[f]=cnt;
}
void add2(int f,int t)
{
    to2[++cnt2]=t;
    next2[cnt2]=head2[f];
    head2[f]=cnt2;
}
bool instack[105];
stack<int> s;
int low[105],dfn[105],belong[105],index,colour;
void tarjan(int u)
{
    s.push(u);
    instack[u]=1;
    low[u]=dfn[u]=++index;
    for(int i=head[u];i!=-1;i=next[i])
    {
        int t=to[i];
        if(!dfn[t])
            tarjan(t),low[u]=min(low[u],low[t]);
        else
            if(instack[t])
                low[u]=min(low[u],dfn[t]);
    }
    if(low[u]==dfn[u])
    {
        ++colour;
        int v;
        while(1)
        {
            v=s.top();
            s.pop();
            instack[v]=0;
            belong[v]=colour;
            if(u==v)
                break;
        }
    }
}
void dfs(int x)
{
    jk[x]=1;
    for(int i=head2[x];i!=-1;i=next2[i])
    {
        int t=to2[i];
        if(!jk[t])
            dfs(t);
    }   
}
int ans1,ans2;
int main()
{
    memset(head,-1,sizeof(head));
    memset(head2,-1,sizeof(head2));,&a))
        {
            if(a!=0)
                add(i,a);
            else
                break;
        }
    }
    for(int i=1;i<=n;i++)
        if(!belong[i])
            tarjan(i);
    for(int i=1;i<=n;i++)
    {
        for(int j=head[i];!=-1;j=ne[j])
        {
            int t=to[jd
            if(belong[i]nbelong[t]&&!vis[belong[i]][belong[t
]]usacois[belong[i]][belong[t]]=复杂度很高
2(belong[i],belo 
g[t]),ru[belong[t]]++;
        }
    }
}

usaco5.3.2()
这个题看上去像是要在平面上直接,模拟,但那样复杂度很高。所以可以直接离线求面积。对于每个询问,四分窗体,如果一片被任意一个“高度”高于它的窗体全部覆盖,那么这片面积为0;如果一片与任何“高度”高于它窗体都不相交,那么这片面积为这片区域大小;否则继续递归。             

struct chuangti
{
    int x1,x2,y11,y2;
    int hao;
}win[65];
int query(int lx,int ly,int rx,int ry,int nu)
{
    for(int i=1;i<=hj;i++)
    {
        if(win[kl[i]].x1<=lx&&win[kl[i]].y11<=ly&&win[kl[i]].x2>=rx&&win[kl[i]].y2>=ry)
        {
            return 0;
        }
        if(win[kl[i]].x1>=rx||win[kl[i]].x2<=lx||win[kl[i]].y11>=ry||win[kl[i]].y2<=ly)
            continue;
        return query(lx,ly,(lx+rx)/2,(ly+ry)/2,nu)+query(lx,(ly+ry)/2,(lx+rx)/2,ry,nu)+query((lx+rx)/2,ly,rx,(ly+ry)/2,nu)+query((lx+rx)/2,(ly+ry)/2,rx,ry,nu);
    }
    return (ry-ly)*(rx-lx); 
}

usaco

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值