USACO2021 Dec.铜组/USACO 2021 December Contest, Bronze 题解

T1 Lonely Photo

题目

Farmer John has recently acquired N new cows (3≤N≤5×105), each of whose breed is either Guernsey or Holstein.

The cows are currently standing in a line, and Farmer John wants take a photo of every sequence of three or more consecutive cows. However, he doesn't want to take a photo in which there is exactly one cow whose breed is Guernsey or exactly one cow whose breed is Holstein --- he reckons this singular cow would feel isolated and self-conscious. After taking a photo of every sequence of three or more cows, he throws out all of these so-called "lonely" photos, in which there is exactly one Guernsey or exactly one Holstein.

Given the lineup of cows, please help Farmer John determine how many lonely photos he will throw out. Two photos are different if they start or end at different cows in the lineup.

Farmer John 最近购入了 N 头新的奶牛(3≤N≤5×105),每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。

奶牛目前排成一排,Farmer John 想要为每个连续不少于三头奶牛的序列拍摄一张照片。 然而,他不想拍摄这样的照片,其中只有一头牛的品种是更赛牛,或者只有一头牛的品种是荷斯坦牛——他认为这头奇特的牛会感到孤立和不自然。 在为每个连续不少于三头奶牛的序列拍摄了一张照片后,他把所有「孤独的」照片,即其中只有一头更赛牛或荷斯坦奶牛的照片,都扔掉了。

给定奶牛的排列方式,请帮助 Farmer John 求出他会扔掉多少张孤独的照片。如果两张照片以不同的奶牛开始或结束,则认为它们是不同的。

思路

我们可以考虑每一头奶牛作为孤独的奶牛对照片数量的贡献。

于是我们可以预处理每只奶牛向左和向右与自己不同种类奶牛的连续长度,最后统计即可。

总结

对于此类题目,我们可以对每只奶牛分别考虑对答案的贡献,通过预处理来求出答案。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 500010
int n, m, i, j, k; 
int l[N], r[N], ans; 
char a[N]; 

signed main()
{
	scanf("%d%s", &n, a+1); 
	for(i=1, k=0; i<=n; ++i)
		if(a[i]==a[i-1]) l[i]=0, ++k; 
		else l[i]=k, k=1; 
	for(i=n, k=0; i>=1; --i)
	{
		if(a[i]==a[i+1]) r[i]=0, ++k; 
		else r[i]=k, k=1; 
	}
	for(i=1; i<=n; ++i)
	{
		if(l[i]&&r[i]) ans+=l[i]*r[i]; 
		if(l[i]>=2) ans+=l[i]-1; 
		if(r[i]>=2) ans+=r[i]-1; 
	}
	printf("%lld", ans); 
	return 0;
}

T2 Air Cownditioning

题目

Farmer John's cows N
are very particular about the room temperature in their barn. Some cows like the temperature to be on the cooler side, while others prefer more warmth.

Farmer John's barn contains a sequence of N
stalls, numbered 1…N, each containing a single cow. The i-th cow prefers the temperature of her stall to be pi, and right now the temperature in her stall is ti. In order to make sure every cow is comfortable, Farmer John installs a new air conditioning system that is controlled in a somewhat interesting way. He can send commands to the system telling it to either raise or lower the temperature in a consecutive series of stalls by 1 unit --- for example "raise the temperature in stalls 5…8

by 1 unit". The series of stalls could be as short as just a single stall.

Please help Farmer John determine the minimum number of commands he needs to send his new air conditioning system so that every cow's stall is at the ideal temperature for its resident cow.

Farmer John 的 N 头奶牛对他们牛棚的室温非常挑剔。有些奶牛喜欢温度低一些,而有些奶牛则喜欢温度高一些。

Farmer John 的牛棚包含一排 N
个牛栏,编号为 1…N,每个牛栏里有一头牛。 第 i 头奶牛希望她的牛栏中的温度是 pi,而现在她的牛栏中的温度是 ti。为了确保每头奶牛都感到舒适,Farmer John 安装了一个新的空调系统。该系统进行控制的方式非常有趣,他可以向系统发送命令,告诉它将一组连续的牛栏内的温度升高或降低 1 个单位——例如「将牛栏 5…8

的温度升高 1 个单位」。一组连续的牛栏最短可以仅包含一个牛栏。

请帮助 Farmer John 求出他需要向新的空调系统发送的命令的最小数量,使得每头奶牛的牛栏都处于其中的奶牛的理想温度。

思路

我们对于需要加的和需要减的分段考虑。

假设有一段是全部要加的。

我们只需要看一下每一个要比前一个多加多少,因为前一个能加的这个也能加,只需要考虑这一个不能加的即可。

要减的同理。

总结

对于此类题目,我们可以大胆猜测可以分情况讨论。同时在考虑变多少的时候,我们可以尝试和相邻的进行比较,看看新加的贡献。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 1000010
int n, m, i, j, k, ans; 
int x[N], a[N], y[N]; 

signed main()
{
	scanf("%lld", &n); 
	for(i=1; i<=n; ++i) scanf("%lld", &x[i]); 
	for(i=1; i<=n; ++i) scanf("%lld", &y[i]); 
	for(i=1; i<=n; ++i) a[i]=max((long long)0, x[i]-y[i]); 
	for(i=1, k=0; i<=n; ++i)
		ans+=max((long long)0, a[i]-k), k=a[i]; 
	for(i=1; i<=n; ++i) a[i]=max((long long)0, y[i]-x[i]); 
	for(i=1, k=0; i<=n; ++i)
		ans+=max((long long)0, a[i]-k), k=a[i]; 
	printf("%lld", ans); 
	return 0;
}

T3 Walking Home

题目

Bessie the cow is trying to walk from her favorite pasture back to her barn.

The pasture and farm are on an N×N
grid (2≤N≤50

), with her pasture in the top-left corner and the barn in the bottom-right corner. Bessie wants to get home as soon as possible, so she will only walk down and to the right. There are haybales in some locations that Bessie cannot walk through; she must walk around them.

Bessie is feeling a little tired today, so she wants to change the direction she walks at most K
times (1≤K≤3

) .

How many distinct paths can Bessie walk from her favorite pasture to the barn? Two paths are distinct if Bessie walks in a square in one path but not in the other

奶牛 Bessie 正准备从她最喜爱的草地回到她的牛棚。

农场位于一个 N×N
的方阵上(2≤N≤50

),其中她的草地在左上角,牛棚在右下角。Bessie 想要尽快回家,所以她只会向下或向右走。有些地方有草堆(haybale),Bessie 无法穿过;她必须绕过它们。

Bessie 今天感到有些疲倦,所以她希望改变她的行走方向至多 K
次(1≤K≤3

)。

Bessie 有多少条不同的从她最爱的草地回到牛棚的路线?如果一条路线中 Bessie 经过了某个方格而另一条路线中没有,则认为这两条路线不同。

思路

\(dp(x, y, k, 0/1)\) 代表此时在格子 \((x,y)\),已转弯 \(k\) 次,现在朝着方向下/右(\(0/1\))的方案数。

然后就可以从左边和上边转移过来,转移的时候需要考虑是否转弯。

总结

对于棋盘上年统计方案的题目,如果棋盘不是很大,可以考虑dp,把限制条件写入转态即可。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n, m, i, j, k, t, kx, p; 
int dp[55][55][5][2], ans; 
char s[55][55]; 

signed main()
{
	scanf("%lld", &t); 
	while(t--)
	{
		memset(dp, 0, sizeof(dp)); ans=0; 
		scanf("%lld%lld", &n, &k); 
		for(i=1; i<=n; ++i) scanf("%s", s[i]+1); 
		if(s[1][1]=='H'){ printf("0\n"); continue; }
		dp[1][1][0][0]=dp[1][1][0][1]=1; 
		for(i=1; i<=n; ++i)
			for(j=1; j<=n; ++j)
				if(s[i][j]=='.')
					for(kx=0; kx<=k; ++kx)
					{
						dp[i][j][kx][0]+=dp[i-1][j][kx][0]; 
						if(kx) dp[i][j][kx][0]+=dp[i][j-1][kx-1][1]; 
						dp[i][j][kx][1]+=dp[i][j-1][kx][1]; 
						if(kx) dp[i][j][kx][1]+=dp[i-1][j][kx-1][0]; 
					}
		for(kx=0; kx<=k; ++kx)
			ans+=(dp[n-1][n][kx][0]+dp[n][n-1][kx][1]); 
		printf("%lld\n", ans); 
	}
	return 0;
}
posted @ 2021-12-21 17:54  zhangtingxi  阅读(993)  评论(0编辑  收藏  举报