ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

USACO 2015 January S 题解

2022-01-03 17:05:41  阅读:169  来源: 互联网

标签:pre const int 题解 ll January 2015 include dis


2015 January S

P3114 [USACO15JAN]Stampede S

本题和区间覆盖有点类似,每头牛所对应的区间就是这头牛能被看到的时间

区间以 \(y\)​ 坐标进行降序排序,直接区间覆盖即可

注意,本题必须用左闭右开区间存储,因为在结束的那一刻是看不见的(已经离开了)

为了存储这些区间,我们采用离散化的方式存储(主要是离散化后可以暴力覆盖)

代码:

#include <map>
#include <set>
#include <cstdio>
#include <algorithm>
typedef long long ll;
using namespace std;
const int inf=0x3f3f3f3f;
const int N=5e4+7;

struct node {
	int b,e,y;
	inline bool operator < (const node &p) const {
		return y>p.y;
	}
}a[N];

map<ll,int> h;

set<ll> s;
set<int> ans;

int vis[N<<2];

int n,cnt;

signed main() {
	scanf("%d",&n);
	for(int i=1;i<=n;++i) {
		ll x,y,r;
		scanf("%lld%lld%lld",&x,&y,&r);
		a[i]={(-x-1)*r,(-x-1)*r+r-1,y}; // 建立区间
		s.insert(a[i].b),s.insert(a[i].e),s.insert(a[i].e+1);
	}
	for(set<ll>::iterator it=s.begin();it!=s.end();++it)
		h[*it]=++cnt; // 离散化
	sort(a+1,a+1+n); // 以 y 坐标进行降序排序
	for(int i=1;i<=n;++i) {
		a[i].b=h[a[i].b],a[i].e=h[a[i].e];
		for(int j=a[i].b;j<=a[i].e;++j)
			vis[j]=i; // 暴力覆盖
	}
	for(int i=0;i<(N<<2);++i)
		ans.insert(vis[i]); // 判断有多少头牛可以被看见
	printf("%d",ans.size()-1); // -1 是因为把看不到牛的时间点也算进去了
    return 0;
}

P3115 [USACO15JAN]Cow Routing S

对每条航线进行建边处理,同时记录两个城市之间的城市数,然后跑最短路即可

注意,本题由于边数比较多,建议用邻接矩阵存储

代码:

#include <queue>
#include <cstdio>
#include <vector>
typedef long long ll;
using namespace std;
const ll inf_ll=1e16;
const int inf_int=0x3f3f3f3f;
const int N=1e3+7;

struct node {
	ll w;
	int num,u;
	inline bool operator < (const node &y) const {
		return w>y.w || (w==y.w && num>y.num);
	}
};

vector<int> plane;

pair<ll,int> edge[N][N];
ll dis[N];
int pre[N];

int s,e,n;

inline void Dijkstra(int s) {
    priority_queue<node> q;
    for(int i=1;i<N;++i)
    	dis[i]=inf_ll,pre[i]=-1;
    dis[s]=0,pre[s]=0;
    q.push({0,0,s});
    while(!q.empty()) {
        node c=q.top();
        q.pop();
        if(c.w!=dis[c.u] || c.num!=pre[c.u])
            continue;
        int u=c.u;
        for(int v=1,num;v<N;++v) {
           	ll w=edge[u][v].first;
           	num=edge[u][v].second;
            if(dis[v]>dis[u]+w || (dis[v]==dis[u]+w && pre[v]>pre[u]+num) ) {
                dis[v]=dis[u]+w;
                pre[v]=pre[u]+num;
                q.push({dis[v],pre[v],v});
            }
        }
    }
}

signed main() {
	scanf("%d%d%d",&s,&e,&n);
	for(int i=1;i<N;++i)
		for(int j=1;j<N;++j)
			edge[i][j]={inf_ll,inf_int};
	for(int i=1,num;i<=n;++i) {
		ll price;
		scanf("%lld%d",&price,&num);
		plane.clear();
		for(int v;num;--num) {
			scanf("%d",&v);
			for(int j=0,u;j<plane.size();++j) {
				u=plane[j];
				if(edge[u][v].first>price)
					edge[u][v]={price,plane.size()-j}; // 当前点到 u 经过这条航线要经过 plane.size()-j 个点
				else if(edge[u][v].first==price && edge[u][v].second>plane.size()-j)
					edge[u][v]={price,plane.size()-j};
			}
			plane.push_back(v);
		}
	}
	Dijkstra(s);
	if(pre[e]==-1)
		puts("-1 -1");
	else
		printf("%lld %d",dis[e],pre[e]);
    return 0;
}

P3116 [USACO15JAN]Meeting Time S

先考虑暴力

设 \(b_{i,j}\)​ 为 \(\tt{Bessie}\)​​ 能否用 \(j\) 的使时间到达第 \(i\)​​ 个点, \(e_{i,j}\)​​​ 为 \(\tt{Elesie}\)​​​​ 能否用 \(j\)​​ 的使时间到达第 \(i\)​​​ 个点

我们通过广搜遍历每一个点(此题为有向无环图),状态转移方程为:

\[b_{v,i+w1}|=b_{u,i} \\ e_{v,i+w2}|=e_{u,i} \]

可以拿到部分分数

考虑优化,暴力的主要缺点是转移完时候可能还有路径到达这个点,造成多次计算

那我们可不可以先把所有可以到达这个点的路径全部遍历完再转移,显然,我们可以用拓扑排序实现

代码如下:

#include <queue>
#include <cstdio>
#include <vector>
using namespace std;
const int N=1e2+7;

struct node {
	int v,w1,w2;
};

vector<node> edge[N];

queue<int> q;

bool bessie[N][N*N],elsie[N][N*N];
int indeg[N];

int n,m;

inline void TopoSort() {
	bessie[1][0]=elsie[1][0]=true;
	for(int i=1;i<=n;++i)
		if(!indeg[i])
			q.push(i);
	while(!q.empty()) {
		int u=q.front();
		q.pop();
		for(int i=0,v,w1,w2;i<edge[u].size();++i) {
			v=edge[u][i].v;
			w1=edge[u][i].w1,w2=edge[u][i].w2;
			
			for(int i=0;i+w1<N*N;++i)
				bessie[v][i+w1]|=bessie[u][i]; 
			for(int i=0;i+w2<N*N;++i)
				elsie[v][i+w2]|=elsie[u][i]; // 状态转移
				
			--indeg[v];
			if(!indeg[v])
				q.push(v);
		}
	}
}

signed main() {
	scanf("%d%d",&n,&m);
	for(int i=1,u,v,w1,w2;i<=m;++i) {
		scanf("%d%d%d%d",&u,&v,&w1,&w2);
		edge[u].push_back({v,w1,w2});
		++indeg[v];
	}
	TopoSort();
	for(int i=0;i<N*N;++i)
		if(bessie[n][i] && elsie[n][i])
			return printf("%d",i),0;
	puts("IMPOSSIBLE");
    return 0;
}

标签:pre,const,int,题解,ll,January,2015,include,dis
来源: https://www.cnblogs.com/wshcl/p/15JanS.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有