C++题集「含分类」「算法与数据结构」(持续更新ing

C++题集目录C++题集DP问题Dice SumKing BombeeChoose Elements搜索问题Shortest Good Path(BFS)思维题Bracket Sequence DeletionMax MinMathK-colinear LinePolynomial division贪心问题Wrapping Chocolate二分问题Range Count Query木材加工跳石头DP问题Dice
摘要由CSDN通过智能技术生成

C++题集


目录

C++题集

DP问题

Dice Sum

King Bombee

Choose Elements

搜索问题

Shortest Good Path(BFS)

思维题

Bracket Sequence Deletion

Max Min

Math

K-colinear Line

Polynomial division

贪心问题

Wrapping Chocolate

二分问题

Range Count Query

木材加工

跳石头


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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值