您的位置:首页 > 其它

多校训练赛 Furude_Rika and wall 解题报告(dp)

2017-05-08 16:55 591 查看

题目大意:

题目描述:

Furude_Rika decided to paint a wall.The wall consists of n*m tiles,that are arranged in an n*m table,

and each tile is a 1*1 square.At the beginning all the tiles are not painted.

Furude_Rika wants to paint the wall that in each row and in each column the number of printed tile

is 0,1 or 2.She wants to know how many different ways she can paint her wall.

As the answer will be too big,mod it by 14020130063.

输入:

Only two intergers n,m(n<=100,m<=100).

输出:

Output an interger,the answer to the problem.

样例输入:

1 3

样例输出:

7

提示:

For every tile you can choose whether to paint it or not,the total way of sample is 2*2*2=8.

but if we paint all the tiles,the number of painted tiles in the 1 row is 3.

so the final answer is 8-1=7.

和我一样的中文爱好者请看此处:

给你一个m*n的方格,让你给它涂颜色,问你有多少种涂色方案。

涂色要求:方格的每一行或者每一列,都只能有不超过2个格子被涂色。

分析:

应该就是动态规划的问题。然后m*n(m行n列)的方格也可以看作是n*m的方格,所以这里让输入数据中较大的数作为n。

dp建立:

确定状态:

这个涂色的过程可以看做是一列一列的上色,然后每一列只能最多涂两个格,这两个格还不能涂在之前已经有两个格被涂过的行上。因为每一列的涂法数量和之前各个行已经被涂过的格数有关,所以设:dp [ i ] [ j ] [ k ] 表示涂到第 i 列的时候,已经有 j 行涂了一个格, k 行被涂了两个格的所有不同涂法数量。

确定状态转移方程:

dp[i][j][k]=dp[i−1][j][k]+dp[i−1][j+1][k−1]∗(j+1)+dp[i−1][j−1][k]∗(m−(j−1)−k)+dp[i−1][j+2][k−2]∗C2j+2+dp[i−1][j−2][k]∗C2m−(j−2)−k+dp[i−1][j][k−1]∗j∗(m−(k−1)−j)

边界条件:

dp[1][0][0]=1;

dp[1][1][0]=m;

dp[1][2][0]=C2m;

代码:

//1
#include<iostream>
#include<stdio.h>
#include<string.h>
#define mod 14020130063
#define maxn 105
using namespace std;

int m,n;
long long int dp[maxn][maxn][maxn];

long long int f(int j,int k,int t)
{
if(k<0||t<0||t>j)return 0;
if(k>min(m,2*j)||k+t>m)return 0;
if(dp[j][k][t]!=-1)return dp[j][k][t];
dp[j][k][t]=f(j-1,k,t)+(k+1)*f(j-1,k+1,t-1)+(m-(k-1)-t)*f(j-1,k-1,t)+(k+2)*(k+1)/2*f(j-1,k+2,t-2)+(m-(k-2)-t)*(m-(k-2)-t-1)/2*f(j-1,k-2,t)+k*(m-(t-1)-k)*f(j-1,k,t-1);
dp[j][k][t]%=mod;
return dp[j][k][t];
}

int main()
{
cin>>m>>n;
memset(dp,-1,sizeof(dp));
if(m>n){int t=m;m=n;n=t;}
dp[1][0][0]=1;
dp[1][1][0]=m;
dp[1][2][0]=m*(m-1)/2;
long long int s=0;

for(int j=0;j<=m;j++)
{
for(int k=0;k<=m-j;k++)
{
//cout<<"f("<<n<<","<<j<<","<<k<<")="<<f(n,j,k)<<endl;
s+=f(n,j,k);
}
}
s%=mod;
cout<<s<<endl;

}


题目地址:

http://acm.xidian.edu.cn/problem.php?cid=1031&pid=0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm 算法 动态规划 dp