C++题集
目录
DP问题
Dice Sum
题目传送门:Atcoder Beginner Contest 248 C Dice Sum (opens new window)
反思:做的时候想到了可能会是DP,但是并没有深入的去想该怎么表示状态,状态转移方程是什么。
思路:
状态表示:dp[i][j]
表示前i个数,和为j。
状态转移方程:dp[i][j] = dp[i][j] + (dp[i-1][0]+dp[i][1]+....)
AC代码
#define int long long
using namespace std;
const int mod = 998244353;
const int N = 60,M=2510;
int dp[N][M];
signed main()
{
int t=1;
while(t--){
int n,m,k;cin>>n>>m>>k;
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
for(int u=1;u<=m;u++){
if(j-u>=0){
dp[i][j] = (dp[i][j] + dp[i-1][j-u]) % mod;
}
}
}
}
int ans = 0;
for(int i=1;i<=k;i++) ans = ( ans + dp[n][i] ) % mod;
cout<<ans<<endl;
}
return 0;
}
King Bombee
题目传送门:Atcoder Beginner Contest 244 E King Bombee (opens new window)
反思:赛时做的时候就以为纯纯图论,但是自己还是不太熟悉,导致完全没有想到是DP。
题解:
先来思考几个问题:
1.为什么是DP?
ans:取模,奇偶,求方案数
2.怎么表示状态?
ans:用dp[i][j][k],三维数组来表示,dp[i][j][k]表示走到值为i,第j个位置时的数量,k则用0/1表示X出现了奇数次还是偶数次。
3.X出现奇数次和偶数次的状态如何表示?
//如果说这个值和X相等
dp[i][j+1][1/0] += dp[i][j][0/1];
//如果不等呢?
dp[i][j+1][1/0] += dp[i][j][1/0];
AC代码:
点击查看代码
//Ryker
#define int long long
using namespace std;
const int mod = 998244353;
int dp[2010][2010][2];
pair<int, int> v[2010];
signed main() {
int N,M,K,S,T,X;
// 数列里面要有k+1个点,全部从1-n里面拿
// 要满足起点是s,终点是t,并且A[i]要和A[i+1]相连
// x出现偶数次
// 思路:dp[i][j][k]表示第i个点,序列中第j个位置,x出现的奇数还是偶数次
cin>>N>>M>>K>>S>>T>>X;
for(int i=1;i<=M;++i){cin>>v[i].first;cin>>v[i].second;}
dp[S][0][0]=1;
for(int i=0;i<K;++i){
for(int j=1;j<=M;++j){
int x = v[j].first;int y=v[j].second;
for(int k=0;k<=1;++k){
// 奇数和偶数的转换
(dp[x][i+1][k] += dp[y][i][k ^ (X==y)]) %= mod;
(dp[y][i+1][k] += dp[x][i][k ^ (X==x)]) %= mod;
}
}
}
cout<<dp[T][K][0]<<endl;
// x x x z
return 0;
}
Choose Elements
题目传送门:Atcoder Beginner Contest 245 C Choose Elements (opens new window)
题意:
给两个数组,A[N],B[N],然后对每个数(i),你可以选择A[i]或者B[i],构成一个数组X[N],要求这个数组满足(X[i]-X[i+1])的绝对值小于K
过程:在赛场上始终想的是必须处理到终点,但我并不会处理(,然后想着DFS必然会TLE,一直在这里犹疑不决。
题解:其实这题可以用DP,首先状态表示是DP[i][2],前i表示走了第i个,第二个维度0表示选A,1表示选B,状态转移的时候注意:如果你前面没走,你后面自然也不能走。
AC代码:
点击查看代码
//Ryker
#define int long long
using namespace std;
const int N = 2e5+10;
int a[N];
int b[N];
int dp[N][2];
int n,k,cnt=0;
signed main() {
int t=1;
while(t--){
cin>>n>>k;
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i