2020.06.25日常總結

UVA11292 Dragon of Loowater\color{green}{\texttt{UVA11292 Dragon of Loowater}}

[Problem]\color{blue}{\texttt{[Problem]}}

你的王國裏有一條有 nn 個頭的 惡龍,你希望僱傭一些 騎士 把它殺死(即砍掉所有頭)。村裏有 mm 個騎士可以僱傭,一個能力值爲 xx 的騎士可以砍掉惡龍一個直徑不超過 xx 的頭,且需要支付 xx 個金幣。如何僱傭騎士才能砍掉龍的所有頭,且需要支付的金幣最少?注意,一個騎士只能砍一個頭且不能被僱傭兩次。

輸入格式:

輸入包含多組數據。
每組數據的第一行爲正整數 nnm(1n,m20000)m(1\leq n,m\leq 20000)
以下 nn 行每行爲一個整數,即惡龍每個頭的直徑;
以下 mm 行每行爲一個整數,即每個騎士的能力。
輸入結束標誌爲 n=m=0n=m=0

輸出格式:
對於每組數據,輸出最小花費。
如果無解,輸出 Loowater is doomed!

[Soluntion]\color{blue}{\texttt{[Soluntion]}}

貪心。

我們肯定不會花大價錢僱一個非常有能力的騎士來砍一個直徑很小的頭。由此可以作爲貪心的依據。

我們把惡龍的頭和騎士的能力值都先從小到大排序。這一步是爲了方便下面的處理。

提示:當我們需要處理的信息很亂,但答案與元素間的相對順序無關時,我們可以考慮通過排序的方法整理數據以方便我們的處理。

我們枚舉騎士,如果它可以砍掉惡龍的一個尚未被砍掉的頭的話,我們就讓它砍。總的時間複雜度是 O(n+m)O(n+m) 的。

[code]\color{blue}{\texttt{[code]}}

#define gc getchar()
#define g(c) isdigit(c)
inline int read(){
	char c=0;int x=0;bool f=0;
	while (!g(c)) f=c=='-',c=gc;
	while (g(c)) x=x*10+c-48,c=gc;
	return f?-x:x;
}
const int N=2e4+100;
int n,m,a[N],b[N],tot,cur;
int main(){
	while (~scanf("%d%d",&n,&m)){
		if (n==0&&m==0) break;//結束標誌 
		for(int i=1;i<=n;i++)//枚舉惡龍 
			a[i]=read();//輸入惡龍謝謝 
		for(int i=1;i<=m;i++)//枚舉騎士 
			b[i]=read();//輸入騎士信息 
		tot=0;cur=1;//初始化,十分重要 
		sort(a+1,a+n+1);//從小到大排序 
		sort(b+1,b+m+1);//從小到大排序 
		for(int i=1;i<=m;i++)//枚舉騎士 
			if (b[i]>=a[cur]){//可以殺 
				cur++;//殺死一個惡龍,要殺下一個 
				tot+=b[i];//僱傭騎士是要付錢的 
				if (cur>n) break;//殺死所有惡龍 
			}
		if (cur>n) printf("%d\n",tot);
		else puts("Loowater is doomed!");
	}
	return 0;
}

UVA10943 How do you add?\color{green}{\texttt{UVA10943 How do you add?}}

[Problem]\color{blue}{\texttt{[Problem]}}

在這裏插入圖片描述

[Soluntion]\color{blue}{\texttt{[Soluntion]}}

fi,jf_{i,j} 表示把 ii 分成 jj 個數字的和的方案數。

我們可以得到如下的狀態轉移方程:

fi,j=k=0ifik,j1f_{i,j}=\sum\limits_{k=0}^{i} f_{i-k,j-1}

其含義是,我們把 iki-k 分成 j1j-1 個和,然後再加上一個數 kk,剛剛好總和就是 ii,分成了 jj 份。

總的時間複雜度爲 O(n2×k)O(n^2\times k),完全可以通過本題 1n,k1001 \leq n,k \leq 100 的數據。

[code]\color{blue}{\texttt{[code]}}

int f[110][110],n,k;
const int mod=1000000;
int main(){
	freopen("t1.in","r",stdin);
	for(int i=0;i<=100;i++)
		f[i][1]=1;//n=i,k=1
	for(int j=2;j<=100;j++)
		for(int i=0;i<=100;i++)
			for(int k=0;k<=i;k++)
				(f[i][j]+=f[i-k][j-1])%=mod;
	while (~scanf("%d%d",&n,&k)){
		if (n==0&&k==0) break;
		printf("%d\n",f[n][k]);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章