[USACO 2016 Dec Gold] Tutorial

Link:

传送门

A:

贪心从小到大插入,用并查集维护连通性

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=1e3+10;
int n,tot,cnt,f[MAXN];P dat[MAXN];
struct edge{int x,y;ll w;}e[MAXN*MAXN];

ll sqr(int x){return 1ll*x*x;}
bool cmp(edge x,edge y){return x.w<y.w;}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&dat[i].X,&dat[i].Y),f[i]=i;
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
            e[++tot]={i,j,sqr(dat[i].X-dat[j].X)+sqr(dat[i].Y-dat[j].Y)};
    sort(e+1,e+tot+1,cmp);

    cnt=n;
    for(int i=1;i<=tot;i++)
    {
        int px=find(e[i].x),py=find(e[i].y);
        if(px!=py) f[px]=py,cnt--;
        if(cnt==1) return printf("%lld",e[i].w),0;
    }
    return 0;
}

Problem A

B:

$dp[1...n][1...m][0/1]$,其中0/1表示当前在哪一边

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=1e3+10,INF=0x3f3f3f3f;
ll dp[MAXN][MAXN][2];
int n,m;P dat[MAXN*2];

ll sqr(int x){return 1ll*x*x;}
ll dist(int a,int b){return sqr(dat[a].X-dat[b].X)+sqr(dat[a].Y-dat[b].Y);}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n+m;i++)
        scanf("%d%d",&dat[i].X,&dat[i].Y);

    memset(dp,0x3f,sizeof(dp));
    dp[1][0][0]=0;
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)
            for(int k=0;k<2;k++)
            {
                if(i) dp[i+1][j][0]=min(dp[i+1][j][0],dp[i][j][0]+dist(i,i+1));
                if(j) dp[i+1][j][0]=min(dp[i+1][j][0],dp[i][j][1]+dist(n+j,i+1));
                if(i) dp[i][j+1][1]=min(dp[i][j+1][1],dp[i][j][0]+dist(i,n+j+1));
                if(j) dp[i][j+1][1]=min(dp[i][j+1][1],dp[i][j][1]+dist(n+j,n+j+1));
            }
    printf("%lld",dp[n][m][0]);
    return 0;
}

Problem B

C:

可以明显发现是最短路模型,但如果将一个点能不转弯走到的所有点的边都连上明显$TLE$

那么在跑最短路时多记录一维当前方向即可,每次转移判断是否要转向来决定是否增加代价

这样只要与不穿过其他点就能到达的点连边就行了

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=1e5+10,INF=0x3f3f3f3f;
int n,x,y,h1[MAXN],h2[MAXN],dist[MAXN][2],tot;
struct edge{int nxt,to;}e1[MAXN<<2],e2[MAXN<<2];
struct node{int x,y,id;}tmp[MAXN],dat[MAXN];
struct Queue{int w,x,dir;};

bool cmp1(node a,node b){return a.x<b.x;}
bool cmp2(node a,node b){return a.y<b.y;}
bool operator < (Queue a,Queue b){return a.w>b.w;}
void add1(int x,int y)
{
    e1[++tot]={h1[x],y};h1[x]=tot;
    e1[++tot]={h1[y],x};h1[y]=tot;
}
void add2(int x,int y)
{
    e2[++tot]={h2[x],y};h2[x]=tot;
    e2[++tot]={h2[y],x};h2[y]=tot;
}
priority_queue<Queue> q;

int main()
{
    scanf("%d",&n);n+=2;
    scanf("%d%d",&x,&y);dat[1]=tmp[1]={x,y,1};
    scanf("%d%d",&x,&y);dat[n]=tmp[n]={x,y,n};
    for(int i=2;i<n;i++)
        scanf("%d%d",&dat[i].x,&dat[i].y),dat[i].id=i,tmp[i]=dat[i];

    sort(tmp+1,tmp+n+1,cmp1);
    for(int i=1;i<n;i++)
        if(tmp[i].x==tmp[i+1].x)
            add1(tmp[i].id,tmp[i+1].id);
    sort(tmp+1,tmp+n+1,cmp2);
    for(int i=1;i<n;i++)
        if(tmp[i].y==tmp[i+1].y)
            add2(tmp[i].id,tmp[i+1].id);

    memset(dist,0x3f,sizeof(dist));
    dist[1][0]=dist[1][1]=0;
    q.push(Queue{0,1,0});q.push(Queue{0,1,1});
    while(!q.empty())
    {
        Queue t=q.top();q.pop();
        if(dist[t.x][t.dir]<t.w) continue;

        for(int i=h1[t.x];i;i=e1[i].nxt)
            if(dist[e1[i].to][0]>dist[t.x][t.dir]+(t.dir!=0))
                dist[e1[i].to][0]=dist[t.x][t.dir]+(t.dir!=0),q.push(Queue{dist[e1[i].to][0],e1[i].to,0});
        for(int i=h2[t.x];i;i=e2[i].nxt)
            if(dist[e2[i].to][1]>dist[t.x][t.dir]+(t.dir!=1))
                dist[e2[i].to][1]=dist[t.x][t.dir]+(t.dir!=1),q.push(Queue{dist[e2[i].to][1],e2[i].to,1});
    }
    int res=min(dist[n][0],dist[n][1]);
    printf("%d",res==INF?-1:res);
    return 0;
}

Problem C

不过看了题解发现由于:

1、同一行/列可以直达任一点

2、每次代价增加必然是行列间转化

从而也可以仅考虑坐标,离散化后对于点$(x,y)$将$x$行和$y$列连边即可

原文地址:https://www.cnblogs.com/newera/p/9615534.html

时间: 2024-09-30 13:52:10

[USACO 2016 Dec Gold] Tutorial的相关文章

[USACO 2011 Dec Gold] Threatening Letter【后缀】

Problem 3: Threatening Letter [J. Kuipers, 2002] FJ has had a terrible fight with his neighbor and wants to send him a nasty letter, but wants to remain anonymous. As so many before him have done, he plans to cut out printed letters and paste them on

【BZOJ1589】【USACO 2008 Dec Gold】 1.Trick or Treat on the Farm 基环树裸DP、

没测样例一遍A这真是-- 题意:每个点都有且仅有一个出边(可以出现自环),然后这样一个点出发就会走过且一定走过某些点. 问每个点出发都会走过几个点. 首先这是基环树无疑. 然后就是裸DP了. 这个的关键就是找环,仅此. #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 101000 using namespace std; int n

[USACO 2018 Open Gold] Tutorial

Link: 传送门 A: 对于每一条分割线,设本不应在其左侧的个数为$x$ 重点要发现每次一来一回的操作恰好会将一对分别应在左/右侧的一个数从右/左移过去 这样就转直接用树状数组求出最大的$x$即可 #include <bits/stdc++.h> using namespace std; #define X first #define Y second typedef long long ll; typedef pair<int,int> P; const int MAXN=1e

USACO翻译:USACO 2013 DEC Silver三题

USACO 2013 DEC SILVER 一.题目概览 中文题目名称 挤奶调度 栅栏油漆 奶牛排队 英文题目名称 msched paint lineup 可执行文件名 msched paint lineup 输入文件名 msched.in paint.in lineup.in 输出文件名 msched.out paint.out lineup.out 每个测试点时限 1秒 1秒 1秒 测试点数目 10 10 10 每个测试点分值 10 10 10 比较方式 全文比较 全文比较 全文比较 二.运

USACO翻译:USACO 2014 DEC Silver三题

USACO 2014 DEC SILVER 一.题目概览 中文题目名称 回程 奶牛IDs 搬家 英文题目名称 piggyback cowids relocate 可执行文件名 piggyback cowids relocate 输入文件名 piggyback.in cowids.in relocate.in 输出文件名 piggyback.out cowids.out relocate.out 每个测试点时限 1秒 1秒 1秒 测试点数目 10 10 10 每个测试点分值 10 10 10 比较

USACO 2016 US Open Contest Gold T3: 248

题目大意 给定一个1*n(2≤N≤248)的地图,在里面玩2048,每次可以合并相邻两个(数值范围1-40),问最大能合出多少.注意合并后的数值并非加倍而是+1,例如2与2合并后的数值为3. 题目分析 观察数据范围与题目,n<=248 并且 “每次可以合并相邻两个” ,不难想到要使用区间DP. 令 f[i][j] 表示区间 i~j 合并的最大值,则显然,转移为 (i < k < j )若f[i][k]==f[k+1][j] 则 f[i][j]=max(f[i][k]+1,f[i][j])

USACO 2016 December Contest Gold T1: Moocast

题目大意 FJ的N头牛(1≤N≤1000)为了在他们之间传播信息, 想要组织一个"哞哞广播"系统. 奶牛们决定去用步话机装备自己而不是在很远的距离之外互相哞哞叫, 所以每一头奶牛都必须有一个步话机. 这些步话机都有一个限制传播半径, 但是奶牛们可以间接地通过中间奶牛传播信息, 所以并不是每头牛都必须直接向其他每一头奶牛连边. 奶牛们需要去决定多少钱花在步话机上, 如果他们花了$X, 那么他们都将会得到sqrt(x)距离的步话机. 所以, 两头牛之间的欧几里得距离平方最多是X. 请帮助奶

USACO 2016 December Contest Gold T3: Lasers and Mirrors

题目大意 出于某种原因,农夫约翰的牛总是在举行激光表演. 对于他们的最新展会,奶牛已经购买了一个大功率的激光器 - 这么大,事实上,他们似乎不能轻易地从它交付的位置移动.他们想以某种方式将激光的光发送到FJ物业另一侧的谷仓.激光器和谷仓都可以被认为位于FJ农场的地图上的2D平面中的点上.牛计划指挥激光器,使得它发出水平或竖直(即,与x或y轴平行)的光束.他们会将这个光束从一些镜子反射回去,直接到谷仓. 在农场上有N个栅栏(1≤N≤100,000),位于不同的二维点(也不同于激光和谷仓),牛可以安

BZOJ 1717 Usaco 2006 Dec 产奶模式

1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1557  Solved: 847[Submit][Status][Discuss] Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个"模式". John的牛奶按质量可以被赋予一个0到10000