反思
做出了A,B,D题,D题是前几天cf的一道启发,c题没做出来,需要反思,因为暴力解法完全能过,当时没考虑,一心想用bfs+状压
e题确实没想到dp,g题倒是想到dp了,但数据量太大不止如何优化。
补题
c题
这题数据范围不大,纯暴力
但也需要状态压缩的技巧
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N=200002;
int d[11];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;
int ans=11;
cin>>n>>m;
for(int i=0;i<n;i++){
string s;
cin>>s;
for(char c:s){
d[i]=(d[i]<<1)+(c=='x');
}
}
for(int i=0;i<(1<<n);i++){
int tmp=(1<<m)-1;
int cnt=0;
for(int j=0;j<n;j++){
if((i>>j)&1){
cnt++;
tmp&=d[j];
}
}
if(!tmp)ans=min(ans,cnt);
}
cout<<ans<<endl;
return 0;
}
E题
dp解法
dp[i][j]含义:只考虑第1~i个字母,规定长度为j,组成的符合条件的字符串数
状态转移方程:dp[i+1][j+k]=d[i][j]+组合数C(j+k,k)
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N=123214;
int mod=998244353;
int sum[27];
ll dp[30][2000];
ll cc[1002][1002];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int k;
int c[30];
cin>>k;
for(int i=1;i<=26;i++){
cin>>c[i];
sum[i]=c[i]+sum[i-1];
}
for(int i=0;i<=k;i++){
cc[i][0]=1;
for(int j=1;j<=i;j++){
cc[i][j]=(cc[i-1][j-1]+cc[i-1][j])%mod;
}
}
for(int i=0;i<=c[1];i++){
dp[1][i]=1;
}
for(int i=2;i<=26;i++){
dp[i][0]=1;
for(int j=1;j<=min(sum[i],k);j++){
for(int m=max(0,j-c[i]);m<=min(j,sum[i-1]);m++){
dp[i][j]=(dp[i][j]+(dp[i-1][m]*1ll*cc[j][m])%mod)%mod;
}
}
}
ll ans=0;
for(int i=1;i<=k;i++)ans=(ans+dp[26][i])%mod;
cout<<ans<<endl;
return 0;
}
F题
真的不想补了,求放过~~
G题
dp解法很显然,但是k<=1e9,若全部遍历会因太大导致dp数组开辟不了
所以需要发现:最佳路径一定是无重复路径,且最终停留于某一点
故最多在n*m步后,它一定会停留在某一点不走
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int N = 123214;
ll dp[3003][51][51];
int A[51][51];
int dx[]={0,0,1,0,-1};
int dy[]={0,1,0,-1,0};
ll inf=1000000000000000001LL;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int h,w,x,y,k1;
int max1=0;
cin>>h>>w>>k1>>x>>y;
for(int i=1;i<=h;i++){
for(int j=1;j<=w;j++){
cin>>A[i][j];
max1=max(max1,A[i][j]);
}
}
for(int i=1;i<=h;i++)
{
for(int j=1;j<=w;j++)
{
for(int t=0;t<=min(k1,2500);t++)dp[t][i][j]=-inf;
}
}
for(int i=0;i<5;i++){
int a=x+dx[i],b=y+dy[i];
if(a>=1 && a<=h && b>=1 && b<=w){
dp[1][a][b]=A[a][b];
}
}
for(int i=1;i<min(2500,k1);i++){
for(int j=1;j<=h;j++){
for(int k=1;k<=w;k++){
if(dp[i][j][k]<0)continue;
for(int d=0;d<5;d++){
int a=j+dx[d],b=k+dy[d];
if(a>=1 && a<=h && b>=1 && b<=w)dp[i+1][a][b]=max(dp[i+1][a][b],dp[i][j][k]+A[a][b]);
}
}
}
}
ll ans=0;
int t=min(2500,k1);
for(int i=1;i<=h;i++){
for(int j=1;j<=w;j++){
ans=max(ans,dp[t][i][j]+A[i][j]*1ll*(k1-t));
}
}
cout<<ans<<endl;
return 0;
}
总结
菜就多练~~!!!