Dynamic planning blog 2

P1233 stick processing - New Ecology of computer science education in Luogu (luogu.com.cn)

Greed + dp, classic LIS, read the problem solution to know that there is such a theorem

dilworth theorem: the minimum number of non descending subsequences is equal to the length of the maximum ascending subsequence.

 #include <bits/stdc++.h>
 using namespace std;
 int n;
 struct node{
     int a,b;
 };
 node x[5001];
 int dp[5001];
 bool com(node &a,node&b){
     if(a.a==b.a){
         return a.b>b.b;
     }
     return a.a>b.a;
 }
 int LIS(){
     int ans=0;
     for(int i=1;i<n;i++){
         for(int k=i-1;k>=0;k--){
             if(x[i].b>x[k].b){
                 dp[i]=max(dp[i],dp[k]+1);
             }
         }
         ans=max(ans,dp[i]);
     }
     return ans;
 }
 int main(){
 ​
     cin>>n;
     for(int i=0;i<n;i++){
         cin>>x[i].a>>x[i].b;
         dp[i]=1;
     }
     sort(x,x+n,com);
     cout<<LIS()<<endl;
     return 0;
 }

[P1091 NOIP2004 improvement group] chorus formation - Luogu | new ecology of Computer Science Education (luogu.com.cn)

I don't know if this question is dp, and I don't dare to ask,

Take each number as the largest number in the middle, and find the number of the most decreasing number on the left and the most increasing number on the right. The answer is the largest sum.

 #include<bits/stdc++.h>
 using namespace std;
 int g[105],f[105],a[105],s[105];
 int main()
 {
     int n;
     cin>>n;
     for(int i=1;i<=n;i++){
         cin>>a[i];
         f[i]=1;
         g[i]=1;
     } 
     for(int i=n-1;i>=1;i--){
         for(int j=i+1;j<=n;j++){
             if(a[i]>a[j]){
                 f[i]=max(f[i],f[j]+1);
             }
         }
     } 
     for(int i=2;i<=n;i++){
         for(int j=1;j<i;j++){
             if(a[i]>a[j])
             {
                 g[i]=max(g[i],g[j]+1);
             }
         }
     } 
     int maxx=0;
     for(int i=1;i<=n;i++)
     {
         s[i]=f[i]+g[i]-1;
         maxx=max(s[i],maxx);
     }
     cout<<n-maxx;
 }

Problem - C - Codeforces (Unofficial mirror site, accelerated for Chinese users)

A two-dimensional prefix and dp, but I didn't do it. After reading it for a year, I don't know where I wrote wrong. www, hang it first and wait until I get stronger. After all, 1700, I don't deserve it now.

 #include <bits/stdc++.h>
 using namespace std;
 int mp[401][401];
 //The two-dimensional prefix sum represents the number of 1 in the rectangle with length a and width b starting from 1 and 1 
 int dp[401][401];
 int main(){
     int t;
     cin>>t;
     while(t--){
         int n,m;
         cin>>n>>m;
         for(int i=1;i<=n;i++){
             for(int k=1;k<=m;k++){
                 char t;
                 cin>>t;
                 mp[i][k]=t-'0';
             }
             memset(dp[i],0,sizeof(dp[i]));
         }
         for(int i=1;i<=n;i++){
             for(int k=1;k<=m;k++){
                 dp[i][k]=dp[i-1][k]+dp[i][k-1]-dp[i-1][k-1]+mp[i][k];
                 //cout<<dp[i][k]<<" "; 
             }
             //cout<<endl;
         }
         int ans=0x3f3f3f3f;
         for(int i=1;i<=n;i++){
             for(int k=1;k<=m;k++){
                 for(int s=i+4;s<=n;s++){
                     for(int j=k+3;j<=m;j++){
                         //The number of zeros of the four sides of a rectangle with (i,k)(s,j) as the vertex plus the number of centers 1
                         int line1=dp[s][j]-dp[s][j-1]-mp[s][j]-(dp[i][j]-dp[i][j-1]);
                         int line2=dp[i][j]-dp[i-1][j]-mp[i][j]-(dp[i][k]-dp[i-1][k]);
                         int line3=dp[s][k]-dp[s][k-1]-mp[s][k]-(dp[i][k]-dp[i][k-1]);
                         int line4=dp[s][j]-dp[s-1][j]-mp[s][j]-(dp[s][k]-dp[s-1][k]);
                         int mid=dp[s][j]-dp[s][k]-dp[i][j]+dp[i][k]-line1-line4-mp[s][j];               
                         int t=(j-k-1)*2+(s-i-1)*2;
                         t=t-line1-line2-line3-line4;
                         t+=mid;
                         //cout<<line1<<" "<<line2<<" "<<line3<<" "<<line4<<" "<<mid<<endl;
                         if(t>ans){
                             break;
                         }
                         ans=min(t,ans);
                     }
                 }
             }
         } 
         cout<<ans<<endl;
     }
     
     return 0;
 }

Problem - D - Codeforces (Unofficial mirror site, accelerated for Chinese users)

It's not a very difficult question, but I still didn't think of it.

In fact, this question only needs to think clearly about two situations

1-undeleted number, longest continuous ascending subsequence

2-deletion number. If a[i] is deleted, the only case that may affect the result is that when a[i-1] < a[i+1], the new result is the longest continuous rising subsequence ending with a[i-1] + the longest continuous rising subsequence starting from a[i+1]

 #include <bits/stdc++.h>
 using namespace std;
 int x[200001];
 int LIS1[200001];
 int LIS2[200001];
 int main(){
     int n;
     cin>>n;
     int ans=0;
     for(int i=0;i<n;i++){
         cin>>x[i];
         LIS1[i]=1;
         LIS2[i]=1;
     }
     for(int i=1;i<n;i++){
         if(x[i]>x[i-1]){
             LIS1[i]=LIS1[i-1]+1;
         }
         ans=max(ans,LIS1[i]);
     }
     for(int i=n-2;i>=0;i--){
         if(x[i]<x[i+1]){
             LIS2[i]=LIS2[i+1]+1;
         }
         ans=max(ans,LIS1[i]);
     }   
     for(int i=0;i<n-2;i++){
         if(x[i]<x[i+2]){
             ans=max(ans,LIS1[i]+LIS2[i+2]);
         }
     }
     cout<<ans<<endl;
     return 0;
 }

Problem - 1492C - Codeforces (Unofficial mirror site, accelerated for Chinese users)

Alas, I'm numb. After reading the solution to the problem, I suddenly realized why I didn't think of it. It seems that I still owe some heat

Prepare two arrays. pre represents the leftmost position that each character in b can match

en stands for the rightmost position that each character in b can match

The answer must be generated in the two adjacent characters of b, that is, the first is the leftmost and the last is the rightmost. You can get the maximum difference through traversal

 #include <bits/stdc++.h>
 using namespace std;
 int pre[200001];
 int en[200001];
 int main(){
     int n,m;
     cin>>n>>m;
     string a,b;
     cin>>a>>b;
     int pos=0;
     for(int i=0;i<a.size();i++){
         while(a[i]!=b[pos]){
             i++;
         }       
         pre[pos]=i;
         pos++;
         if(pos==b.size()){
             break;
         }
     }
     pos=b.size()-1;
     for(int i=a.size()-1;i>=0;i--){
         while(a[i]!=b[pos]){
             i--;
         }       
         en[pos]=i;
         pos--;
         if(pos==b.size()){
             break;
         }
     }
     int ans=0;
     for(int i=1;i<b.size();i++){
         ans=max(ans,en[i]-pre[i-1]);
     }
     cout<<ans<<endl;
     return 0;
 }

1463 -- Strategic game (poj.org)

After listening to the explanation of Lord zwt, I suddenly realized that the main idea of the topic is to give you a tree, in which you can select any number of nodes to put sentinels, and then the edge with this point as the en dp oint will be monitored. It is required to place at least how many sentinels so that all edges can be covered

Idea: for the dp problem on the tree, we start from the root node. There are only two cases: I chose the root node and I didn't choose the root node (that is, to place sentries)

1 - select the root node, and then the adjacent edges are covered. It doesn't matter whether his sons put sentinels or not

2 - if you don't choose the root node, each of his sons must put sentinels

Thus, two dimensions dp[n] [2] can be defined, dp[i] [0] represents taking the ith node as the root node without selecting the minimum number of sentinels required by the ith node, and dp[i] [1] represents taking the ith node as the root node and selecting the minimum number of sentinels required by the ith node, so the state transition equation is

Where n is the child of u and num is the number of sons of U

When implementing, just update dp in the backtracking process of dfs (the time complexity of dfs on the tree is O(n))

 #include <iostream>
 #include <cstdio>
 #include <vector>
 #include <string.h>
 using namespace std;
 vector<int>mp[1501];
 int in[1501];
 int dp[1501][2];
 int n;
 ​
 void dfs(int now){
     if(mp[now].size()==0){
         dp[now][0]=0;
         dp[now][1]=1;
         return;
     }
     for(int i=0;i<mp[now].size();i++){
         dfs(mp[now][i]);
     }   
     for(int i=0;i<mp[now].size();i++){
         dp[now][1]+=min(dp[mp[now][i]][1],dp[mp[now][i]][0]);
         dp[now][0]+=dp[mp[now][i]][1];
     }
     dp[now][1]++;
 }
 ​
 int main(){ 
     while(scanf("%d",&n)!=EOF){
         memset(in,0,sizeof(in));
         memset(mp,0,sizeof(mp));
         memset(dp,0,sizeof(dp));
         for(int i=0;i<n;i++){
             int x;
             char t;
             scanf("%d",&x);
             scanf("%c%c",&t,&t);
             int num;
             scanf("%d",&num);
             scanf("%c",&t);
             for(int k=0;k<num;k++){
                 int y;
                 scanf("%d",&y);
                 mp[x].push_back(y);
                 in[y]++; 
             }
         }
         int root=0;
         for(int i=0;i<n;i++){
             //cout<<in[i]<<" ";
             if(in[i]==0){
                 root=i;
                 break;
             }
         }
         dfs(root);
         printf("%d\n",min(dp[root][0],dp[root][1]));
     }
     
     return 0;
 }

Conclusion: most of the luck components of the weekly competition are 1800 questions. I can't do 1500 questions at ordinary times. Wuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwuwu.

Tags: Algorithm Dynamic Programming

Posted on Sat, 16 Oct 2021 00:55:54 -0400 by kaozdragon