看数据范围n<=10,所以不是搜索就是状压dp,又因为搜索会超时所以用dp
dp[i][k][j]表示现已经放到第i行,前面共有k个,这一行状态为j
so,dp[i][k][j]=dp[i-1][k-num[j]][t]
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define low_bit(x) x&-x; using namespace std; inline long long read() { long long f=1,ans=0;char c; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return ans*f; } long long dp[11][1001][1001];//dp[i][j][k]表示前i行放k个且第i行的状态为j long long n,k,s[1001],num[1001]; long long cont(long long x) { long long c=0; while(x!=0) { x-=low_bit(x); c++; } return c; } int main() { n=read(),k=read(); long long ans=0; for(long long i=0;i<(1<<n)-1;i++) { if((i&(i<<1)))continue; s[++ans]=i; num[ans]=cont(i); } dp[0][1][0]=1; // for(long long i=1;i<=ans;i++) cout<<s[i]<<" ";cout<<endl; for(long long i=1;i<=n;i++) { for(long long j=1;j<=ans;j++) { for(long long kk=0;kk<=k;kk++) { if(kk>=num[j]) { for(long long t=1;t<=ans;t++) { if(s[t]&s[j]) continue; if(s[t]&(s[j]<<1)) continue; if(s[t]&(s[j]>>1)) continue; dp[i][j][kk]+=dp[i-1][t][kk-num[j]]; // cout<<dp[i][j][k]<<endl; } } } } } long long sum=0; for(long long i=1;i<=ans;i++) sum+=dp[n][i][k]; cout<<sum; }
#loj 10171. 「一本通 5.4 例 2」牧场的安排
一道比较普通的状压dp,关键点就是输入时候怎么处理荒草
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define mod 100000000 using namespace std; inline long long read() { long long f=1,ans=0;char c; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return ans*f; } long long m,n; //dp[i][j]表示第i行用第j个状态 //dp[i][j]+=dp[i-1][k] long long dp[20][10001]; long long ans[20];//ans[i]表示第i行有ans[i]个状态 long long s[20][10001];//s[i][j]表示第i行第j个状态 void init(long long h,long long t) { // cout<<t<<endl; for(long long i=0;i<=(1<<n)-1;i++) { if((i&(i<<1))||(i&(i>>1))||(i&t)) continue; s[h][++ans[h]]=i; } return; } int main() { m=read(),n=read(); for(long long i=1;i<=m;i++) { long long s=0; for(long long j=1;j<=n;j++) { long long x=read(); s=(s<<1)+1-x; } init(i,s); } for(long long i=1;i<=ans[1];i++) dp[1][i]=1; // for(long long i=1;i<=m;i++) // { // cout<<ans[i]<<endl; // for(long long j=1;j<=ans[i];j++) cout<<s[i][j]<<" "; // system("pause"); // } // for(long long i=2;i<=m;i++) { for(long long j=1;j<=ans[i];j++) { for(long long k=1;k<=ans[i-1];k++) { // cout<<i<<" "<<j<<" "<<k<<" "<<s[i][j]<<" "<<s[i-1][k]<<endl; if(s[i][j]&s[i-1][k]) continue; // if((s[i][j]>>1)&s[i-1][k]) continue; // if((s[i][j]<<1)&s[i-1][k]) continue; dp[i][j]+=dp[i-1][k]%mod; } } } long long sum=0; for(long long i=1;i<=ans[m];i++) sum+=dp[m][i]%mod,sum%=mod; cout<<sum%mod; }