[关闭]
@exut 2024-11-01T02:48:12.000000Z 字数 1823 阅读 156

codeforces 2000~2100 DP

DP codeforces


我发现我状态设计水平好低

CF296B

sol

并没有想出一个好的直接做法(据说是容斥可做),考虑

表示前 位存不存在数字使得 的方案数

转移是平凡的,枚举新数即可,答案是 ,本题不太在乎常数可以使用纯循环加位运算的写法,好实现

复杂度 ,大概常数巨大有个 的样子吧

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int N=1e5+5;
  5. const int mod=1e9+7;
  6. int f[N][2][2];
  7. int n;
  8. char s[N],w[N];
  9. signed main(){
  10. cin>>n;
  11. for(int i=1;i<=n;i++) cin>>s[i];
  12. for(int i=1;i<=n;i++) cin>>w[i];
  13. f[0][0][0]=1;
  14. for(int i=1;i<=n;i++){
  15. int a,b;
  16. for(int j=0;j<2;j++){
  17. for(int k=0;k<2;k++){//枚举来时的状态
  18. for(int nxt1=0;nxt1<=9;nxt1++){
  19. if(s[i]=='?' or s[i]==(nxt1+'0')){
  20. for(int nxt2=0;nxt2<=9;nxt2++){
  21. if(w[i]=='?' or w[i]==(nxt2+'0')){
  22. (f[i][j|(nxt1>nxt2)][k|(nxt1<nxt2)]+=f[i-1][j][k])%=mod;
  23. }
  24. }
  25. }
  26. }
  27. }
  28. }
  29. }
  30. cout<<f[n][1][1]<<"\n";
  31. }

总结

本题启发:当当前位状态和前后都完全无关的时候可以考虑直接用 这种简单状态设计,没有一点后效性。同时在时间允许的情况下可以多循环一点来简约实现也是没有问题的,善于利用位运算。

评价:线性dp,难度大概中位绿,蓝有点虚高了

CF41D

sol

没太懂这玩意哪来的绿,可能看错题了?

难点应该在于输出方案吧,但是这种方案输出方式可以参考 atcoder dp contest 里面 lcs 这道题,思路是相似的

把问题转化成一个判断性问题先,设 表示能不能在走到 列的时候获得 个豌豆,这样设空间一点不紧张,这道题给的太宽松了,不太好评价

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. using namespace std;
  4. const int N=105;
  5. bool f[N][N][N*10+5];
  6. int n,m,k;
  7. char s[N][N];
  8. void out(int J,int W){
  9. cout<<J<<"\n";
  10. for(int i=n;i>1;i--){
  11. if(J>1)
  12. if(f[i-1][J-1][W-s[i][J]+'0']){
  13. cout<<"L";
  14. W-=(s[i][J]-'0');
  15. J--;
  16. continue;
  17. }
  18. if(J<m)
  19. if(f[i-1][J+1][W-s[i][J]+'0']){
  20. cout<<"R";
  21. W-=(s[i][J]-'0');
  22. J++;
  23. continue;
  24. }
  25. }
  26. }
  27. signed main(){
  28. ios::sync_with_stdio();
  29. cin.tie(0),cout.tie(0);
  30. cin>>n>>m>>k;
  31. k++;
  32. for(int i=1;i<=n;i++){
  33. for(int j=1;j<=m;j++){
  34. cin>>s[i][j];
  35. }
  36. }
  37. for(int i=1;i<=m;i++) f[1][i][s[1][i]-'0']=1;
  38. for(int i=2;i<=n;i++){
  39. for(int j=1;j<=m;j++){
  40. for(int w=(s[i][j]-'0');w<=1000;w++){
  41. if(j>1)f[i][j][w]|=f[i-1][j-1][w-s[i][j]+'0'];
  42. if(j<m)f[i][j][w]|=f[i-1][j+1][w-s[i][j]+'0'];
  43. }
  44. }
  45. }
  46. int ans=-1;
  47. for(int w=1000;w>=0;w--){
  48. if(w%k==0){
  49. for(int j=1;j<=m;j++){
  50. if(f[n][j][w]){
  51. cout<<w<<"\n";
  52. out(j,w);
  53. return 0;
  54. }
  55. }
  56. }
  57. }
  58. cout<<-1;
  59. return 0;
  60. }

总结

本题启发:两维状态处理不了就多开一维就好了,输出方向反向转移即可

评价:除去输出就是水

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注