USACO 2016 open Silver 解题报告

来源:互联网 发布:windows 7 共享 选项卡 编辑:程序博客网 时间:2024/05/16 10:35

Sliver1

农夫约翰的N(5<=N<=50000)头牛被定在了平面内的不同的位置。他想用栅栏(平行于xy)围住所有的牛。他想这个栅栏尽可能小(牛在边界上也被视作围住)

他因为牛奶产量低而感到经费紧张,所以他想卖掉三头牛再围起剩下的牛。请算出栅栏围出的最小面积。

输入:

第一行输入n

剩下2-n+1行,输入每头牛的位置。

输出:
最小面积。

示例

input

6

1 1

7 8

10 9

8 12

4 100

50 7

output

12

 

这题和Bronze的第三题差不多。只不过要去掉三头奶牛罢了,既然如此,枚举就不可以了。但是,我们发现,和最小面积相关的就只有去掉外面三层奶牛之后(假如去掉的是中间部分,那么,面积是不会受到影响的),奶牛在x,y轴的最大与最小位置相关。所以,我们用一个DFS,就可以把去掉外面三层所有的状态求出来,再求最小值就可以了。而时间复杂度是O((3^4)*n)。

#include<algorithm>
#include<climits>
#include<fstream>
#include<iostream>
using namespace std;
const int maxn = 50010;
const int inf = INT_MAX;
struct Tnode {
int x, y, id;
} a1[maxn], a2[maxn];
ifstream fin("reduce.in");
ofstream fout("reduce.out");
int n;
long long ans = inf;
bool used[maxn];
bool byX(Tnode, Tnode);
bool byY(Tnode, Tnode);
void dfs(int);
int main() {
fin >> n;//fout<<n<<endl;return 0;

for(int i = 0; i != n; ++i) {
fin >> a1[i].x >> a1[i].y;
a1[i].id = i;
a2[i] = a1[i];
}

sort(a1, a1 + n, byX);
sort(a2, a2 + n, byY);
dfs(0);
fout << ans << endl;
return 0;
}
bool byX(Tnode i, Tnode j) {
return i.x < j.x;
}
bool byY(Tnode i, Tnode j) {
return i.y < j.y;
}
void dfs(int k) {
if(k == 3) {
int maxx, maxy, minx, miny;
maxx = maxy = -inf;
minx = miny = inf;

for(int i = 0; i != n; ++i)
if(!used[a1[i].id]) {
maxx = max(maxx, a1[i].x);
maxy = max(maxy, a1[i].y);
minx = min(minx, a1[i].x);
miny = min(miny, a1[i].y);
}

ans = min(ans, (long long)(maxx - minx) * (maxy - miny));
return;
}

int i;

for(i = 0; i != n && used[a1[i].id]; ++i);

used[a1[i].id] = true;
dfs(k + 1);
used[a1[i].id] = false;

for(i = n - 1; i != -1 && used[a1[i].id]; --i);

used[a1[i].id] = true;
dfs(k + 1);
used[a1[i].id] = false;

for(i = 0; i != n && used[a2[i].id]; ++i);

used[a2[i].id] = true;
dfs(k + 1);
used[a2[i].id] = false;

for(i = n - 1; i != -1 && used[a2[i].id]; --i);

used[a2[i].id] = true;
dfs(k + 1);
used[a2[i].id] = false;
}

                                Diamond Collector(Silver)

         奶牛Bessie很喜欢闪亮亮的东西(Baling~Baling~),所以她喜欢在她的空余时间开采钻石!她现在已经收集了N颗不同大小的钻石(N<=50,000),现在她想在谷仓的两个陈列架上摆放一些钻石。

    Bessie想让这些陈列架上的钻石保持相似的大小,所以她不会把两个大小相差K以上的钻石同时放在一个陈列架上(如果两颗钻石的大小差值为K,那么它们可以同时放在一个陈列架上)。现在给出K,请你帮Bessie确定她最多一共可以放多少颗钻石在这两个陈列架上。

 

输入格式(diamond.in:

    第一行输入两个值NK0<=K<10,000)

         接下来N行,每行是一个整数,分别表示第1~N颗钻石的大小。

         数据保证钻石的大小为正数且不超过10,000.

 

输出格式(diamond.out):

         输出仅一个数,为Bessie能在这两个陈列架上摆的钻石总数的最大值。

 

输入样例:

7 3

10

5

1

12

9

5

14

 

输出样例:

5

 

这题就有些难度了。首先,我们可以预处理,记l[i]为在区间[1,i]里最多能放多少个钻石(其中包括i),r[i]为区间[i,n]里最多能放多少个钻石(其中也包括i),这个可以用单调队列来实现。然后,我们就枚举划分点,也就是说,记这个划分点为k,第一个陈列架上,在前k个选能摆放钻石个数的最大值,而第二个陈列架上,放的是从k到n能摆放钻石的最大值,这两个最大值,也是可以预处理的。最后,只要输出这两个最大值的和的最大值就可以了。

#include <cstdio>#include <algorithm>#include <iostream>using namespace std;int n,k;int i,j;int ans;int a[50010],l[50010],r[50010],ll[50010],rr[50010];int main(){freopen("diamond.in","r",stdin);freopen("diamond.out","w",stdout);scanf("%d%d",&n,&k);for(i=1;i<=n;i++) scanf("%d",&a[i]);sort(a+1,a+n+1);for(i=1;i<=n;i++) l[i]=1;j=1;for(i=1;i<=n;i++){for(; j<=n;j++){if(a[j]-a[i]<=k){l[j]=max(l[j],j-i+1);}else break;}r[i]=j-i;}ll[1]=l[1];for(i=2;i<=n;i++) ll[i]=max(ll[i-1],l[i]);//rr[n]=r[n];for(i=n-2;i>=1;i--) rr[i]=max(rr[i+1],r[i+1]);for(i=1;i<=n;i++)ans=max(ans,rr[i]+ll[i]);printf("%d\n",ans);return 0;}



Sliver3

【题目描述】

FJ和他的奶牛们正在计划离开小镇做一次长的旅行,同时FJ想临时地关掉他的农场以节省一些金钱。

 

这个农场一共有被用M条双向道路连接的N个谷仓(1<=N,M<=3000)。为了关闭整个农场,FJ计划每一次关闭掉一个谷仓。当一个谷仓被关闭了,所有的连接到这个谷仓的道路都会被关闭,而且再也不能够被使用。

 

FJ现在正感兴趣于知道在每一个时间(这里的“时间”指在每一次关闭谷仓之后的时间)时他的农场是否是“全连通的”——也就是说从任意的一个开着的谷仓开始,能够到达另外的一个谷仓。注意自从某一个时间之后,可能整个农场都开始不会是“全连通的”。

 

【输入格式】

输入的第一行是NM。下面的M行每行都描述了一条连接两个谷仓的双向路径的两个端点(输入的点保证在1...N的范围内),最后的N行是一个1...N的排列,描述每一个谷仓被关闭的顺序。

 

【输出顺序】

输出一共有N行,每行可以是“YES”或者“NO”。第一行表示一开始时整个农场是否是“全连通的”,然后第i+1行表示在第i次的关闭谷仓之后整个农场是否是“全连通的”。

 

【样例输入】

4 3

1 2

2 3

3 4

3

4

1

2

 

 

【样例输出】

YES
NO
YES
YES

 

这题是一道水题,因为数据只有3000,而金牌组的那一题n<=200000,至于数据大时怎么做,我在金牌组那里会讲。在这题当中,只要每次把边删掉,在判断一下图是否全联通就可以了。而判断图是否联通可以用DFS用O(n)的时间就算出来了。所以,时间复杂度是O(N*M)。

 

#include <cstdio>#include <vector>#include <iostream>#include <cstring>using namespace std;

bool b[100100],b1[100010];int num[100010];vector<int > f[3010];int n,m,root;int x,y;int sum;

void dfs(int k){ if(b1[k]==1||b[k]==1) return; sum++; b1[k]=1; for(int i=0;i<f[k].size();i++)   dfs(f[k][i]);}int main(){ freopen("closing.in","r",stdin); freopen("closing.out","w",stdout);  memset(b,0,sizeof(b)); scanf("%d%d",&n,&m);  for(int i=1;i<=m;i++) {  scanf("%d%d",&x,&y);  f[x].push_back(y);  f[y].push_back(x); } for(int i=1;i<=n;i++) scanf("%d",&num[i]);  root=num[n]; for(int i=1;i<=n;i++) {  memset(b1,0,sizeof(b1));    sum=0;    //printf("%d:",num[i]);    dfs(root);    if(sum==n-i+1) printf("YES\n");  else printf("NO\n");    b[num[i]]=1; }

 return 0;}

 

0 0
原创粉丝点击