【賽時總結】 ◇賽時·III◇ AtCoder ABC-099

◆賽時·III◆ ABC-099


■嘮叨■

不要問我爲何先給ABC-100寫了博客再寫的ABC-099…… 莫名以爲此次比賽特別簡單……雖然我並無參加比賽,只是以後再補作的。QwQspa


■試題&解析■

◇不動腦子◇ A-ABD

  • 【Atcoder ABC-099 A】
  • 【翻譯】 從ABC開始舉辦的數十年後, 每輪比賽被編號爲 ABC-001,ABC-002...,可是第999輪比賽後,一個問題產生了:如何給以後的比賽編號? 最後,決定第1000輪到第1998輪被依次編號爲 ABD-001,ABD-002... 求第N輪比賽(1≤N≤1998)的編號的前3位(ABC or ABD)
  • 【解析】 其實看樣例就可以看出來——當N≤999時,輸出ABC,不然輸出ABD。就不解釋了(⊙ᗜ⊙)
  • 【源代碼】
/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
	int n;scanf("%d",&n);
	printf("%s",n<=999? "ABC":"ABD");
	return 0;
}

◇論英語的重要性◇ B-Stone Monument

  • 【Atcoder ABC-099 B】
  • 【翻譯】 在一些村莊裏,共有999座塔自西向東排列,第i座塔的高度爲 (1+2+3+...+i)米。 雪下了好久才停,咱們測量了兩個相鄰的塔分別露出雪面的高度,靠西的塔是A米,靠東的塔是B米。 若村莊的地面相平,且雪覆蓋深度相同(即雪在各處的高度是同樣的),給出A,B,求積雪的深度。保證有解。
  • 【解析】 雖然我知道這道題有數學方法,但仍是直接上大暴力……先算出999座塔的高度。再直接枚舉第i座塔,若是第i-1座塔(靠西)的高度減去A等於第i座塔的高度減去B,即雪的深度。
  • 【源代碼】
/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int tower[1005];
int main()
{
	for(int i=1;i<=999;i++)
		tower[i]=tower[i-1]+i;
	int a,b;
	scanf("%d%d",&a,&b);
	for(int i=2;i<=999;i++)
		if(tower[i-1]-a==tower[i]-b)
		{
			printf("%d\n",tower[i-1]-a);
			return 0;
		}
	return 0;
}

◇奇怪,真的奇怪◇ C-Strange Bank

  • 【Atcoder ABC-099 C】
  • 【翻譯】 爲了令人們取錢更困難(????),一家銀行在提款時只容許取走1日元、6的冪日元(如六、3六、216)以及9的冪日元。且不容許將取出的錢再存入,請問取出N日元最少須要提款多少次?
  • 【解析】 實際上是一個相似於徹底揹包的揹包問題…… 簡單地定義狀態dp[i]表示取出n日元的最少次數。那麼物品有1,6,36,...,9,81,...日元。最終狀態是dp[n]。 因而我就用記憶化搜索,當前錢數爲x,每次枚舉取出錢數i(i < x),dp[x]=min{dp[x-i]}。
  • 【源代碼】
/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,dp[100005];
int DP(int x)
{
	if(x<0) return 1e8;
	if(x==0) return 0;
	if(dp[x]!=-1) return dp[x];
	dp[x]=1e8;
	for(int i=6;i<=x;i*=6)
		dp[x]=min(dp[x],DP(x-i)+1);
	for(int i=9;i<=x;i*=9)
		dp[x]=min(dp[x],DP(x-i)+1);
	dp[x]=min(dp[x],DP(x-1)+1);
	return dp[x];
}
int main()
{
	scanf("%d",&n);
	memset(dp,-1,sizeof dp);
	printf("%d\n",DP(n));
	return 0;
}

◇壓軸大暴力?◇ D-Good Grid

  • 【Atcoder ABC-099 D】
  • 【翻譯】 有一個N*N的正方形,(i,j)表示i行j列。 共有C種顏色,這個正方形的全部塊都被塗上了這些顏色。若某一個塊上原來塗的是顏色x,要將其改成顏色j,則須要花費C[i][j]。 特別的,對於(i,j),令F(i,j)=(i+j)%3,則給出改變顏色的花費和該正方形本來每一個塊塗上的顏色,求出要使F(i,j)值不一樣的格子塗的顏色不一樣,F(i,j)值相同的格子塗的顏色相同的最小花費。
  • 【解析】 用tot[x][y]統計F(i,j)=x的格子中,本來顏色爲y的格子的個數。而後枚舉3種不一樣的格子(模3餘0,1,2)將要被塗成的顏色,分別計算每一種格子須要的花費,最後統計取最小值。簡單說來就是大暴力,時間複雜度大概是 O(顏色種類數^3)=O(27000)。 好像時間複雜度也不是特別大……(o^^)o
  • 【源代碼】
/*Lucky_Glass*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXCOL=30;
int n_col,siz,spd[MAXCOL+5][MAXCOL+5];
int tot[3][MAXCOL+5];
int main()
{
	scanf("%d%d",&siz,&n_col);
	for(int i=0;i<n_col;i++)
		for(int j=0;j<n_col;j++)
			scanf("%d",&spd[i][j]);
	for(int i=0;i<siz;i++)
		for(int j=0;j<siz;j++)
		{
			int col;
			scanf("%d",&col);
			tot[(i+j+2)%3][col-1]++;
		}
	int ans=1e9;
	for(int i=0;i<n_col;i++)
	{
		int A=0;
		for(int col=0;col<n_col;col++)
			A+=tot[0][col]*spd[col][i];
		for(int j=0;j<n_col;j++)
			if(i!=j)
			{
				int B=0;
				for(int col=0;col<n_col;col++)
					B+=tot[1][col]*spd[col][j];
				for(int k=0;k<n_col;k++)
					if(i!=k && j!=k)
					{
						int C=0;
						for(int col=0;col<n_col;col++)
							C+=tot[2][col]*spd[col][k];
						ans=min(ans,A+B+C);
					}
			}
	}
	printf("%d\n",ans);
	return 0;
}

The End

Thanks for reading!

- Lucky_Glass翻譯

相關文章
相關標籤/搜索