2 条题解

  • 0
    @ 2025-6-30 15:07:54

    自己口了一个做法,然后上锣鼓发现是对的。

    这里来说一说。

    首先我们考虑直接对这个玩意 DPDP,我们可以把这些颜色一个一个插入进去。

    然后你发现其实相邻同色块似乎特别重要。

    然后清奇的脑回路告诉你要这样设计状态:fi,jf_{i,j} 表示前 ii 种,然后你有 jj 个相邻同色块。

    然后你注意到你往里放可以打破颜色块,也可以不打破。于是你可以枚举我这一次要往里面放几个打破颜色块的新颜色。然后就可以转移了。

    • 0
      @ 2025-6-28 20:55:33

      本题使用记忆化搜索,但是好像有优秀的 DP 更快,这里讲记搜做法。

      首先暴力 dfs 就可以拿到 50 分。

      电风扇:

      #include<bits/stdc++.h>
      #define int long long
      #define mod 1000000007
      using namespace std;
      int k,n,a[20],ans,mp[100];
      void dfs(int u){
      	if(u==n+1){
      		++ans;
      		if(ans>=mod)ans-=mod;
      	}
      	for(int i=1;i<=k;++i){
      		if(mp[u-1]!=i&&a[i]){
      			mp[u]=i,--a[i];
      			dfs(u+1);
      			++a[i];
      		}
      	}
      }
      signed main(){
      	cin>>k;
      	for(int i=1;i<=k;++i){
      		cin>>a[i];
      		n+=a[i];
      	}
      	dfs(1);
      	cout<<ans<<"\n";
      	return 0;
      }
      

      然后我们优化,由于相邻的不能涂同种颜色,所以直接 DP 比较困难,我们考虑记忆化搜索。

      然后你的参数必须能够准确概括状态,注意到 5155^{15} 非常大,但是 15515^5 就不那么大,所以我们可以设:

      dp[a][b][c][d][e][lst] 表示还能涂1,2,3,4,5个的颜色分别还有 aabbccddee种,并且上一次涂的是还能用 lstlst 次的颜色(现在只能用 lst1lst-1 次了)。

      所以如果你这一次用的是还能用一次的一个,有 aa 种选择,但是如果你上一次用的还能用两次的,他这次就会加入到还能用一次的里面,所以如果 lst=2lst=2 则这一次可用的颜色数会减一。

      其他的同理。

      #include<bits/stdc++.h>
      #define int long long
      #define mod 1000000007
      using namespace std;
      int n,k,a[20];
      int dp[16][16][16][16][16][6];
      int t[6];
      int dfs(int a,int b,int c,int d,int e,int lst){
      	if(dp[a][b][c][d][e][lst]!=-1)return dp[a][b][c][d][e][lst];
      	if(a+b+c+d+e==0)return 1;
      	int ans=0;
      	if(a)ans+=(a-(lst==2))*dfs(a-1,b,c,d,e,1);
      	if(b)ans+=(b-(lst==3))*dfs(a+1,b-1,c,d,e,2);
      	if(c)ans+=(c-(lst==4))*dfs(a,b+1,c-1,d,e,3);
      	if(d)ans+=(d-(lst==5))*dfs(a,b,c+1,d-1,e,4);
      	if(e)ans+=e*dfs(a,b,c,d+1,e-1,5);
      	dp[a][b][c][d][e][lst]=ans%mod ;
      	return ans%mod;
      }
      signed main() {
      	cin>>k;
      	for(int i=1;i<=k;++i){
      		cin>>a[i];++t[a[i]];
      	}
      	memset(dp,-1,sizeof dp);
      	cout<<dfs(t[1],t[2],t[3],t[4],t[5],0);
      	return 0;
      }
      
      • 1

      信息

      ID
      303
      时间
      1000ms
      内存
      256MiB
      难度
      6
      标签
      (无)
      递交数
      31
      已通过
      10
      上传者