SMU Autumn 2024 Trial 2

A. Stand-up Comedian
只要a不为0,那么由于b和c是相互制约的,比如2 5 10 6这个样例,讲完两个笑话以后两个人的容量为2 2,可以选择一个人+1,一个人-1,那么就可进行min(b,c)*2次,进行完后,两个人的容量仍为2,2,最后要看还剩几个笑话可以讲,就是min(a+1,abs(b-c)+d),就是容量很大时可以把笑话全讲完,如果容量小于剩下的笑话,就只能讲当前容量+1个笑话

#include<bits/stdc++.h>
using namespace std;


int main() {
	
	int n;
	cin>>n;
	while(n--)
	{
		int a,b,c,d;
		cin>>a>>b>>c>>d;
		if(a==0) {
			cout<<1<<endl;
			continue;
		}
		int ans=0;
		ans+=a;//两个人都增加
		ans+=min(b,c)*2;//相互制约
		ans+=min(a+1,abs(b-c)+d);//剩下的可以讲的笑话,某个为0时
		cout<<ans<<endl;
		
	}
	
}

B. Harmony Analysis
++++++++
++++????
++??++??
++????++
+?+?+?+?
+?+??+?+
+??++??+
+??+?++?
我们用问号来代替*号会发现,当k=3时,后四行是由前四行偶数位异或得到的

#include<bits/stdc++.h>
using namespace std;
int n,m=1,a[512][512];
/*void print(int m)
{
for(int i=0;i<m;i++)
{
for(int j=0;j<m;j++) cout<<a[i][j];
cout<<endl;

}
}
*/
int main()
{
	a[0][0]=1,cin>>n;
	for(int i=1;i<=n;i++)
	{
			//print(m);
		for(int j=0;j<m;j++)for(int k=m*2-1;k>=0;k--)a[j][k]=a[j][k/2];
		//把每一行对半复制比如10 复制为1100
		for(int j=m;j<m*2;j++)for(int k=0;k<m*2;k++)a[j][k]=a[j-m][k];
		//把后一半行复制成前一半行
		for(int j=m;j<m*2;j++)for(int k=1;k<m*2;k+=2)a[j][k]^=1;
		//后一半行偶数位异或
	
		m*=2;
		//cout<<endl;
	}
	
	for(int i=0;i<m;i++)
	{
		for(int j=0;j<m;j++) {
			if(a[i][j]==1) cout<<"+";
			else cout<<"*";
		}
		cout<<endl;
	}
	
	
	//print(m);
	return 0;
}

C. Armchairs
动态规划
\(f[i][j]\)用来记录前i个人坐了前j把椅子的最小代价,i为前i个人,j为前j把椅子。
预处理一下,把有人坐的位置放进b数组里
\(如果当前位置没有人(a[j]==0),则f[i][j]=min(f[i-1][j-1]+abs(b[i]-j,f[i][j-1]))\)
\(如果有人坐了,则f[i][j]=f[i][j-1]\)

#include<bits/stdc++.h>
using namespace std;
int t,n,a[5005],f[5005][5005],b[5005];
//f[i][j] i是前i个人 j是前j把椅子 f[i][j]为前i个人坐了前j把椅子的最小费用
int main() {
	
	int n;
	int cnt=0;
	cin>>n;
	for(int i=1;i<=n;i++) {
		cin>>a[i];
		if(a[i]==1)	b[++cnt]=i;//把有人坐的位置放进b数组里
	}
	memset(f,0x3f3f3f,sizeof (f));//先把每个位置的代价设置为无限大
	//注意memset赋值最大值只能写0x3f3f3f
	for(int i=0;i<=n;i++) f[0][i]=0;//第一行代价为0,0个人任意坐任意把椅子没有代价
	
	
	
	for(int i=1;i<=cnt;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[j]==0){//当前位置没有人,考虑是否可以坐,f[i-1][j-1]是当前行的上一行的最优解
				f[i][j]=min(f[i][j-1],f[i-1][j-1]+abs(b[i]-j));
			}else//有人了,代价就是前一个值
				f[i][j]=f[i][j-1];
		}
	}

	cout<<f[cnt][n]<<endl;//此时输出的就是最小代价
	
}

D. Maximum Subarray
这道题是最大子段和的进阶版,大概是2000分的题目,我先放着,等我日后再来补补
https://www.luogu.com.cn/problem/solution/CF1796D 别人的题解

posted on 2024-09-18 20:18  swj2529411658  阅读(9)  评论(0编辑  收藏  举报

导航