1. 程式人生 > >牛客網36-A,B題解

牛客網36-A,B題解

A.Rabbit的字串

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld

題目描述

Rabbit得到了一個字串,她的好朋友xxx可以給這個字串施加一次魔法。

魔法可以選擇字串的任一位置,並將該位置後面的所有字元水平拼接到串首。

例如:對於字串abcde,可以通過施加魔法得到cdeab。

如果xxx通過施加魔法將字串的字典序變得嚴格比之前的小,那麼他將拿走這一字串。

Rabbit想知道自己的字串會不會被xxx拿走。

輸入描述:

第一行一個整數n,表示字串的長度。

接下來一行一個長度為n的只由小寫字母組成的字串。

輸出描述:

如果Rabbit的字串會被xxx拿走,輸出“YES”。
否則輸出“NO”。
(不輸出引號)

示例1

輸入

複製

5
cdeab

輸出

複製

YES

說明

xxx可以把e之後的部分“ab”放到串首,得到abcde,字典序比cdeab小,故將拿走字串。

示例2

輸入

複製

5
abcde

輸出

複製

NO

備註:

1≤n≤100000

字典序的說明:https://en.wikipedia.org/wiki/Alphabetical_order

思路:此題的想法是我的i想法是直接找後邊是否存在比它小的,但是我們要考慮相等的時候,比如,abcab,這樣也可以,我們可以試著將相等的複製到一個新的串中,然後拼接一下,但是我是水了一下他的資料

程式碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;
char str[100005];

int main()
{
	
	int n;
	cin>>n;
	scanf("%s",str);
	int flag=0;
	for(int t=1;t<n;t++)
	{
		if(str[t]<str[0])
		{
			flag=1;
		  cout<<"YES"<<endl;
		  return 0;
		}
	}
	char str1[100005];
	for(int t=1;t<n;t++)
	{
		if(str[t]==str[0]&&str[t+1]<str[1]&&str[t+2]<str[2])
		{
			flag=1;
			cout<<"YES"<<endl;
			return 0; 
		}
	}
	if(flag==0)
	{
		cout<<"NO"<<endl;
	}
	return 0;
	
	return 0;
 } 

B.Rabbit的工作(1) 

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld

題目描述

Rabbit大學畢業後找到了一份實習工作,如果實習通過她就轉正了。
實習期共有N天,其中有幾天公司集體放假,Rabbit不用上班,剩下時間她可以選擇工作或者休息。Rabbit工作總是越來越累,可是每當她休息時,她就重新充滿了能量。簡而言之,Rabbit第一天工作時這一天會消耗體力1,連續第二天工作時這一天會消耗體力2,連續第三題工作時這一天會消耗體力3,以此類推......每當她休息後,工作的第一天又會消耗體力1。
為了讓boss滿意,Rabbit想工作儘量多的天數,但是懶惰的Rabbit又想讓自己的總體力消耗不超過K。 

輸入描述:

第一行兩個整數N,K。

第二行一個長度為N的01字串。如果第i個字元為‘1’,表示這一天Rabbit可以選擇工作或者休息,否則這一天Rabbit放假。

輸出描述:

輸出Rabbit最多能工作的天數。

示例1

輸入

複製

4 2
1011

輸出

複製

2

說明

第三天和第四天裡面休息一天即可,總體力消耗為2

備註:

1<=N<=400

1<=K<=N∗(N+1)/2

思路:可以用dp來做

設d[ i ][ j ][ p ]為在 i 天時,一共工作了 j 天,且連續工作了 p 天直到第 i 天時花費的最小體力。那麼轉移方程很簡單:

如果第 i 天我不工作,那麼對於所有的合法的 p,d[ i ][ j ][ 0 ]=max( d[ i-1 ][ j ][ p ] ),如果我第 i 天工作,那麼對於所有合法的 j 和 p,d[ i ][ j ][ p ]=d[ i-1 ][ j-1 ][ p-1 ]+p,然後對於所有的d[ i ][ j ][ p ]<=k,取一個最大的 j 當答案即可。

程式碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int d[405][405][35],n,k,ans;
char s[160000];
int main()
{
	cin>>n>>k>>s+1;
	memset(d,-1,sizeof(d));
	d[0][0][0]=0;
	for(int i=1;i<=n;i++)
	{
		if(s[i]=='1')
		{
			for(int j=1;j<=n;j++)
			for(int p=1;p*(p+1)/2<=n;p++)
			if(d[i-1][j-1][p-1]!=-1)
			{
				d[i][j][p]=d[i-1][j-1][p-1]+p;
				if(d[i][j][p]<=k)
				ans=max(ans,j);
			}
		}		
		for(int j=0;j<=n;j++)
		for(int p=0;p*(p+1)/2<=n;p++)
		if(d[i-1][j][p]!=-1)
		{
			if(d[i][j][0]==-1)d[i][j][0]=d[i-1][j][p];
			else
			d[i][j][0]=min(d[i-1][j][p],d[i][j][0]);
			if(d[i][j][0]<=k)
			ans=max(ans,j);
		}
	}
	cout<<ans;
}