DP精选
非常棒的DP
F. Igor and Mountain
rating:1800
评述:
并不能说此题很难,如果能充分理解题意的话就是一道中等难度的DP
代码
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#if !defined(ONLINE_JUDGE) && defined(LOCAL)
#include "helper.h"
#else
#define dbg(...) ;
#define local_go_m(x) int c;cin>>c;while(c--)x()
#endif
template<class T>
constexpr T power(T a, i64 b) {
T res = 1;
for (; b != 0; b /= 2, a *= a) {
if (b & 1) {
res *= a;
}
}
return res;
}
template<int M>
struct ModInt {
public:
constexpr ModInt() : x(0) {}
template<std::signed_integral T>
constexpr ModInt(T x_) {
T v = x_ % M;
if (v < 0) {
v += M;
}
x = v;
}
constexpr int val() const {
return x;
}
constexpr ModInt operator-() const {
ModInt res;
res.x = (x == 0 ? 0 : M - x);
return res;
}
constexpr ModInt inv() const {
return power(*this, M - 2);
}
constexpr ModInt &operator*=(const ModInt &rhs) &{
x = i64(x) * rhs.val() % M;
return *this;
}
constexpr ModInt &operator+=(const ModInt &rhs) &{
x += rhs.val();
if (x >= M) {
x -= M;
}
return *this;
}
constexpr ModInt &operator-=(const ModInt &rhs) &{
x -= rhs.val();
if (x < 0) {
x += M;
}
return *this;
}
constexpr ModInt &operator/=(const ModInt &rhs) &{
return *this *= rhs.inv();
}
friend constexpr ModInt operator*(ModInt lhs, const ModInt &rhs) {
lhs *= rhs;
return lhs;
}
friend constexpr ModInt operator+(ModInt lhs, const ModInt &rhs) {
lhs += rhs;
return lhs;
}
friend constexpr ModInt operator-(ModInt lhs, const ModInt &rhs) {
lhs -= rhs;
return lhs;
}
friend constexpr ModInt operator/(ModInt lhs, const ModInt &rhs) {
lhs /= rhs;
return lhs;
}
friend constexpr std::istream &operator>>(std::istream &is, ModInt &a) {
i64 i;
is >> i;
a = i;
return is;
}
friend constexpr std::ostream &operator<<(std::ostream &os, const ModInt &a) {
return os << a.val();
}
friend constexpr std::strong_ordering operator<=>(ModInt lhs, ModInt rhs) {
return lhs.val() <=> rhs.val();
}
private:
int x;
};
constexpr int M = 998244353;
using Z = ModInt<M>;
void go() {
int n,m,d;std::cin>>n>>m>>d;
std::vector<std::string> a(n);
for(int i=0;i<n;i++)std::cin>>a[i];
std::vector f(n,std::vector<Z>(m,0));
auto merge=[&](int row,int dis)->std::vector<Z>{
std::vector<Z> c(m,0);
int l=0,r=1;
Z cur=f[row][l];
for(int i=0;i<m;i++){
while(r<m&&r-i<=dis)cur+=f[row][r++];
while(l<m&&i-l>dis)cur-=f[row][l++];
c[i]=cur;
}
return c;
};
auto hor=[&](int row)->void{
auto c=merge(row,d);
for(int i=0;i<m;i++){
if(a[row][i]=='X')f[row][i]=c[i];
}
};
for(int j=0;j<m;j++){
if(a[n-1][j]=='X')f[n-1][j]=1;
}
hor(n-1);
int d2=int(sqrt(i64(d)*d-1));
for(int i=n-2;i>=0;i--){
auto c=merge(i+1,d2);
for(int j=0;j<m;j++){
if(a[i][j]=='X')f[i][j]=c[j];
}
hor(i);
}
Z res=0;
for(int i=0;i<m;i++)res+=f[0][i];
std::cout<<res<<'\n';
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
local_go_m(go);
return 0;
}
F - Happy Birthday! 3
rating:2100
思路:区间DP
其实只有两种操作:1是单独修改,2是区间修改。如何考虑区间修改呢?我们在c[k]==c[r]时考虑区间修改的情况。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 810;
int n, c[N], x[N];
int f[N][N];
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; ++ i ) cin >> c[i], c[i + n] = c[i];
for (int i = 1; i <= n; ++ i ) cin >> x[i];
for (int i = 1; i <= n * 2; ++ i ) {
f[i][i] = x[c[i]] + 1;
}
for(int len=2;len<=n;len++){
for(int l=1;l+len-1<=2*n;l++){
int r=l+len-1;
f[l][r]=f[l][r-1]+f[r][r];
for(int k=l;k<r;k++){
if(c[k]==c[r])f[l][r]=std::min(f[l][r],f[l][k]+r-k+f[k+1][r-1]);
}
}
}
int res = 1e18;
for (int l = 1, r = n; r <= 2 * n; ++ l, ++ r ) res = min(res, f[l][r]);
cout << res;
return 0;
}
天梯赛L3难度
评述
练习暴搜和DP+溯源。
代码
#include <bits/stdc++.h>
using pii = std::pair<int,int>;
using u64 = unsigned long long;
using i64 = long long;
const int N = 1e5+5;
namespace ranges = std::ranges;
void solve(){
int n,m;std::cin>>n>>m;
std::vector<int> a(n+1);
for(int i=1;i<=n;i++)std::cin>>a[i];
std::sort(a.begin()+1,a.end(),std::greater());
std::vector f(n+1,std::vector<int>(m+1));
std::vector pre(n+1,std::vector<int>(m+1));
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
f[i][j]=f[i-1][j];
if(j-a[i]>=0&&f[i][j]<=f[i-1][j-a[i]]+a[i]){
f[i][j]=f[i-1][j-a[i]]+a[i];
pre[i][j]=1;
}
}
}
std::vector<int> ans;
if(f[n][m]==m){
int id=n;
while(m){
if(pre[id][m]){
ans.push_back(a[id]);
m-=a[id];
}
id--;
}
for(int i=0;i<ans.size();i++){
if(i!=ans.size()-1)std::cout<<ans[i]<<' ';
else std::cout<<ans[i];
}
std::cout<<'\n';
}else{
std::cout<<"No Solution\n";
}
}
signed main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(2);
int t = 1, i;
for (i = 0; i < t; i++){
solve();
}
return 0;
}