Acwing 271. 杨老师的照相排列

Acwing 271. 杨老师的照相排列

题意:

有n个数分别是从1到n,现在排成k排,每排分别有Ci个数,要求每排每列的都是从小到大,问有多少种方案

题解:

因为每行每列都是单调的,因此我们可以从小到大一次考虑1 ~ n的位置。在任意时刻,已经安排好的位置的数在每一行都是递增关系的(因为我们是从小到大的安排),每个数都插在队尾。我们用一个5元组来表示每行的人数,(a1,a2,a3,a4,a5),ai表示第i行已经安排好的人数,当此时考虑下一步(即再安排一个新人时),我们考虑所有满足如下条件的行号i:

  1. ai<Ci
  2. i=1或 a i − 1 > a i a_{i-1}>a_{i} ai1>ai

从上往下考虑,如果当前行未满,并且当前行人数小于上一行。(如果上一行人数比本行小,那应该优先放在上一行,记住我们是从小到大放置,所以必须顺序放,不然无法保证单调性)
如果满足条件,就对该行进行转移,该行人数+1,加上上一个状态的方案。

我们不需要关心(a1,a2,a3,a4,a5)这些已经排好的具体方案,其描述的轮廓内的合影方案总数就构成一个子问题。
注意直接开数组会爆,使用动态开数组

代码:

#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\n",a,b);
typedef long long ll;
using namespace std;
//Fe~Jozky
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){
   ll s=0,w=1ll;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
   return s*w;
}
void rd_txt(){
	#ifdef ONLINE_JUDGE
	#else
    	freopen("in.txt","r",stdin);
	#endif
}
int k;
int a[10];
int main()
{
	//rd_txt();
	while(cin>>k){
		if(k==0)break;
		a[1]=a[2]=a[3]=a[4]=a[5]=0;
		for(int i=1;i<=k;i++){
			cin>>a[i];
		}
		unsigned int f[a[1]+2][a[2]+2][a[3]+2][a[4]+2][a[5]+2];
		memset(f,0,sizeof(f));
		f[0][0][0][0][0]=1;
		
		for(int i1=0;i1<=a[1];i1++){
			for(int i2=0;i2<=a[2];i2++){
				for(int i3=0;i3<=a[3];i3++){
					for(int i4=0;i4<=a[4];i4++){
						for(int i5=0;i5<=a[5];i5++){
							unsigned int x=f[i1][i2][i3][i4][i5];
							if(i1<a[1])f[i1+1][i2][i3][i4][i5]+=x;
							if(i2<a[2]&&i2<i1)f[i1][i2+1][i3][i4][i5]+=x;
							if(i3<a[3]&&i3<i2)f[i1][i2][i3+1][i4][i5]+=x;
							if(i4<a[4]&&i4<i3)f[i1][i2][i3][i4+1][i5]+=x;
							if(i5<a[5]&&i5<i4) f[i1][i2][i3][i4][i5+1]+=x;
						}
					}
				}
			}
		}
		
		cout<<f[a[1]][a[2]][a[3]][a[4]][a[5]]<<endl;
	}
	return 0;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值