传送:https://codeforces.com/contest/1248/problem/C
题目:n x m的网格 (10^5),给网格涂上白黑两色,要求一种颜色网格最多有一个相同颜色的网格和它相邻,问总共有多少种涂色方案?答案对10^9取模。
思路:说实话,当时没想出来,但知道应该是dp。
我们可以从第一行开始考虑。
1. 如果第一行有 两个相同颜色格子相邻 的情况,那么与这行相邻的下一行也就随之确定,以此类推,整个网格的涂色就确定了。
此种情况,方案数为 第一行涂色方案数 - 第一行相邻格子交替涂色方案数 (黑白相间+白黑相间=2)。
2. 如果第一行不存在 两个相同颜色格子相邻 的情况,即该行网格总是 白黑相间,那么与这行相邻的下一行也就不存在 两个相同颜色格子相邻 的情况,以此类推。此种情况,方案数为 第一列涂色方案数。只要第一列确定,每一行的第一格也就确定,每一行白黑相间 也就一种情况。
我们用一个二维数组dp[maxn][2]来为维护一行网格的涂色方案数。
dp[i][0] 表示第i个位置涂白色 的方案数
dp[i][0] = dp[i-1][1] + dp[i-2][1]
第i个位置为白色,那么可以由两种情况转移而来
dp[i][1] 表示第i个位置涂黑色 的方案数
dp[i][1] = dp[i-1][0] + dp[i-2][0]
第i个位置为黑色,那么可以由两种情况转移而来
二者综合,dp[i][0] + dp[i][1] = dp[i-1][1] + dp[i-1][0] + dp[i-2][1] + dp[i-2][0] -> dp[i] = dp[i-1] + dp[i-2]
总方案数,即 dp[m] - 2 + dp[n]
代码:
#include
#define LL long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=100005;
const int mod=1e9+7;
int n,m;
LL dp[maxn];
int main()
{
cin>>n>>m;
ios::sync_with_stdio(false);
dp[1]=2;
dp[2]=4;
for(int i=3;i<=max(n,m);i++)
{
dp[i]=dp[i-1]+dp[i-2];
dp[i]%=mod;
}
LL ans=(dp[n]+dp[m]-2+mod)%mod;
cout << ans << endl;
return 0;
}
传送:https://codeforces.com/contest/1249/problem/E
题目:有一栋n层的楼房,有两种方式上楼,乘坐电梯和爬楼梯,爬楼梯给出了从下面一层到这层需要花费的时间a[1]...a[n-1]
乘坐电梯也给出了从下面一层到这层需要花费的时间b[1]...b[n-1],但乘上电梯前需要等待c时间,问从第一层到达各层楼需要花费的最小时间分别是多少?
思路:很明显也是dp递推,一开始我用了贪心的思路,以为第i层的最优解,只是从前一层的最优直接转移而来,这是个错误的做法,因为该层的最优解还可能是之前的次优解转移而来。(通过错误代码体会)
而正确的做法应该用一个二维数组dp[maxn][2],去维护结果
dp[i][0] 表示上一步是通过爬楼梯到达此层的最小时间
dp[i][1] 表示上一步是通过坐电梯到达此层的最小时间
dp[i][0]=min(dp[i-1][0]+a[i-1],dp[i-1][1]+a[i-1])
dp[i][1]=min(dp[i-1][0]+b[i-1]+c,dp[i-1][1]+b[i-1])
错误代码:
#include
#define LL long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=200005;
const int mod=1e9+7;
LL a[maxn],b[maxn],dp[maxn];
int main()
{
ios::sync_with_stdio(false);
int n,c;
cin>>n>>c;
for(int i=1;i>a[i];
}
for(int i=1;i>b[i];
}
dp[1]=0;
int flag=1;//代表是否可以无需等待乘坐电梯
for(int i=2;i<=n;i++)
{
dp[i]=dp[i-1];
if(a[i-1]
正确代码:
#include
#define LL long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn=200005;
const int mod=1e9+7;
LL a[maxn],b[maxn];
LL dp[maxn][2];
int main()
{
ios::sync_with_stdio(false);
int n,c;
cin>>n>>c;
for(int i=1;i>a[i];
}
for(int i=1;i>b[i];
}
dp[1][0]=0;
dp[1][1]=INF;
cout << 0 << ' ';
for(int i=2;i<=n;i++)
{
dp[i][0]=min(dp[i-1][0]+a[i-1],dp[i-1][1]+a[i-1]);
dp[i][1]=min(dp[i-1][0]+b[i-1]+c,dp[i-1][1]+b[i-1]);
cout << min(dp[i][0],dp[i][1]) << ' ';
}
cout << endl;
return 0;
}