LOJ#10172. 涂抹果酱【状压DP】

题目描述 https://loj.ac/problem/10172

看完题目,很清楚的想到这道题用状压DP来做,只不过这道题是个三进制的,做题过程中须注意转换。

下面简单说一下算法
1. 用0 1 2 来代替题目中的1 2 3这样比较方便,将第k行以三进制数存入。先用一个数组存所以可行的状态,若第k行的状态不在数组里,直接输出0.
2. 这道题中已经给出了一行的状态,所以搜到k行要特判

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int modd=1e6;
int ans[10005][2187],st[2187],f,an,n,m,tot,pp;
int jud(int x)
{
	int tp=0x3f;
	for(int i=1;i<=m;i++)
	{
		if(tp==x%3) return 0;
		tp=x%3,x/=3;
	}
	return 1;
}
int ff(int x,int y)
{
    for(int i=1;i<=m;i++)
    {
    	if(x%3==y%3) return 0;
    	x/=3,y/=3;
	}
	return 1;
}
int main()
{ int k;

   scanf("%d%d%d",&n,&m,&k);
   int cnt=1;
   for(int i=1;i<=m;i++)
   {
   	  int a;
   	  scanf("%d",&a);
   	  f=f*3+a-1;
   	  cnt=cnt*3;
   }
   for(int i=0;i<cnt;i++)
     if(jud(i)==1) st[++tot]=i;
   for(int i=1;i<=tot;i++)
     if(f==st[i])
     {
     	pp=i; break;
	 }
   if(pp==0) 
   {
   	  cout<<0; return 0;
   }//ans[i][j]表示第i行 状态为j的方案数 
   for(int i=1;i<=n;i++)
   {
   	  if(i==k)
   	  {  
   	     if(i==1) ans[i][pp]=1;
   	     else 
   	       for(int j=1;j<=tot;j++)//枚举上一行状态 
   	         if(ff(st[pp],st[j])==1)
   	           ans[i][pp]=(ans[i][pp]+ans[i-1][j])%modd;
	  }
	  else
	    for(int j=1;j<=tot;j++)//枚举本行状态 
	    {
	        if(i==1) ans[i][j]=1;
			else 
			  for(int p=1;p<=tot;p++)//枚举上一行状态 
			    if(ff(st[j],st[p])==1) 
				  ans[i][j]=(ans[i][j]+ans[i-1][p])%modd;	 
		}
   }
   for(int i=1;i<=tot;i++)
     an=(an+ans[n][i])%modd;
   printf("%d",an);	     
 	
  return 0;	
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值