• 区间DP day42


    昨天放假了^_^

    今天也只做了三题

    感觉颓废了ww

    不过今天认识很多大一牌爷orz

    明天能以他们为目标好好努力嘛

    不过今天从ygg哪里学到了dp的一些理解

    我们状态表示时 要完备 要不重不漏的每一个情况都算到

    并且我们中间的操作 也要以状态表示为基础顺序来做

    不然肯定是会出差错的

    1068. 环形石子合并

    我超今天我才知道我是第二重循环写错了

    平常都是写的三重循环水过去

    其实我们只要右端点不超过n《1 就可以了

    1. #include
    2. using namespace std;
    3. const int N = 410;
    4. const int M = 1<<12;
    5. const int mod = 1e9+7;
    6. #define int long long
    7. #define endl '\n'
    8. #define Endl '\n'
    9. #define _ 0
    10. #define inf 0x3f3f3f3f3f3f3f3f
    11. #define fast ios::sync_with_stdio(false);cin.tie(nullptr);
    12. int max(int x,int y){return x>y?x:y;}
    13. int min(int x,int y){return x
    14. int f[N][N],s[N];
    15. signed main(){
    16. fast
    17. int n;cin>>n;
    18. int a[N];
    19. for(int i=1;i<=n;i++)cin>>a[i],a[i+n]=a[i];
    20. for(int i=1;i<=n<<1;i++)s[i]=s[i-1]+a[i];
    21. int res=inf;
    22. memset(f,0x3f3f,sizeof f);
    23. for(int i=1;i<=2*n;i++)f[i][i]=0;
    24. for(int len=2;len<=n;len++){
    25. for(int i=1,j=i+len-1;j<=n<<1;i++,j++){
    26. for(int k=i;k
    27. f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
    28. if(len==n)res=min(res,f[i][j]);
    29. }
    30. }
    31. }
    32. cout<
    33. memset(f,0,sizeof f);
    34. int ans=0;
    35. for(int len=2;len<=n;len++){
    36. for(int i=1,j=i+len-1;j<=n<<1;i++,j++){
    37. for(int k=i;k
    38. f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
    39. ans=max(ans,f[i][j]);
    40. }
    41. }
    42. }
    43. cout<
    44. return ~~(0^_^0);
    45. }

    AcWing 1069. 凸多边形的划分

    我们找到一个分界点(最重要的就是

    然后我们就可以很快得到状态表示就是

    f_i_j 表示的是 i点到j的min

    然后就可以分治来做了

    高精度麻烦点(贴板子就行了

    注意不要整inf了 直接empty inf 肯定没有高精度大啊

    1. #include
    2. using namespace std;
    3. const int N = 410;
    4. const int M = 1<<12;
    5. const int mod = 1e9+7;
    6. #define int long long
    7. #define endl '\n'
    8. #define Endl '\n'
    9. #define _ 0
    10. #define inf 0x3f3f3f3f3f3f3f3f
    11. #define fast ios::sync_with_stdio(false);cin.tie(nullptr);
    12. int max(int x,int y){return x>y?x:y;}
    13. int min(int x,int y){return x
    14. vector<int>f[N][N];
    15. int n,w[N];
    16. bool cmp(vector<int> &a, vector<int> &b)
    17. {
    18. if (a.size() != b.size()) return a.size() < b.size();
    19. for (int i = a.size() - 1; i >= 0; i -- )
    20. if (a[i] != b[i])
    21. return a[i] < b[i];
    22. return true;
    23. }
    24. vector<int> add(vector<int> a, vector<int> b)
    25. {
    26. vector<int> c;
    27. int t = 0;
    28. for (int i = 0; i < a.size() || i < b.size(); i ++ )
    29. {
    30. if (i < a.size()) t += a[i];
    31. if (i < b.size()) t += b[i];
    32. c.push_back(t % 10);
    33. t /= 10;
    34. }
    35. while (t) c.push_back(t % 10), t /= 10;
    36. return c;
    37. }
    38. vector<int> mul(vector<int> a, int b)
    39. {
    40. vector<int> c;
    41. int t = 0;
    42. for (int i = 0; i < a.size(); i ++ )
    43. {
    44. t += b * a[i];
    45. c.push_back(t % 10);
    46. t /= 10;
    47. }
    48. while (t) c.push_back(t % 10), t /= 10;
    49. return c;
    50. }
    51. signed main(){
    52. fast
    53. cin>>n;
    54. for(int i=1;i<=n;i++)cin>>w[i];
    55. for(int len=3;len<=n;len++){
    56. for(int i=1,j=len+i-1;j<=n;i++,j++){
    57. for(int k=i+1;k
    58. auto new_val = mul(mul({w[i]}, w[k]), w[j]);
    59. new_val = add(add(new_val, f[i][k]), f[k][j]);
    60. if (f[i][j].empty() || cmp(new_val, f[i][j])) f[i][j] = new_val;
    61. }
    62. }
    63. }
    64. for(int i=f[1][n].size()-1;i>=0;i--)cout<1][n][i];
    65. return ~~(0^_^0);
    66. }

    321. 棋盘分割

    五维确实想对了 状态表示想过正解 可是不知道咋写 感觉推不过去

    而正解也没推状态表示 而是直接的记忆化搜索 这何尝不是一种取舍

    可是此题要求一个min值

    我们只好先初始化成一个极小值 让后进去避过记忆化搜索返回时再初始化为一个很大的值

    1. #include
    2. using namespace std;
    3. const int N = 16;
    4. const int M = 1<<12;
    5. const int mod = 1e9+7;
    6. #define int long long
    7. #define endl '\n'
    8. #define Endl '\n'
    9. #define _ 0
    10. #define inf 0x3f3f3f3f3f3f3f3f
    11. #define fast ios::sync_with_stdio(false);cin.tie(nullptr);
    12. double f[N][N][N][N][N];
    13. int n,s[N][N];
    14. double X;
    15. double get(int x1,int y1,int x2,int y2){
    16. double sum=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]-X;
    17. return sum*sum/n;
    18. }
    19. double dp(int x1,int y1,int x2,int y2,int k){
    20. auto &v=f[x1][y1][x2][y2][k];
    21. if(v>=0)return v;
    22. if(k==1)return v=get(x1,y1,x2,y2);
    23. v=1e9;
    24. for(int i=x1;i
    25. v=min(v,dp(x1,y1,i,y2,k-1)+get(i+1,y1,x2,y2));
    26. v=min(v,dp(i+1,y1,x2,y2,k-1)+get(x1,y1,i,y2));
    27. }
    28. for(int i=y1;i
    29. v=min(v,dp(x1,y1,x2,i,k-1)+get(x1,i+1,x2,y2));
    30. v=min(v,dp(x1,i+1,x2,y2,k-1)+get(x1,y1,x2,i));
    31. }
    32. return v;
    33. }
    34. signed main(){
    35. fast
    36. cin>>n;
    37. for(int i=1;i<=8;i++){
    38. for(int j=1;j<=8;j++){
    39. cin>>s[i][j];
    40. s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
    41. }
    42. }
    43. X=(double)s[8][8]/(double)n;
    44. memset(f,128,sizeof f);
    45. printf("%.3lf",sqrt(dp(1,1,8,8,n)));
    46. return ~~(0^_^0);
    47. }

  • 相关阅读:
    IT基础设施管理
    南大通用GBase8s 常用SQL语句(283)
    (免费领源码)hadoop#Mysql离线与实时的离线与实时的电影推荐系统10338-计算机毕业设计项目选题推荐
    odoo13 升级odoo15时注意点
    大数据(十):数据可视化(二)
    Swin Transformer理论讲解
    golang进程启动及监控
    java(类加载)
    ubuntu 18.04 server源码编译安装freeswitch 1.10.7支持音视频通话、收发短信——筑梦之路
    封装api的理解
  • 原文地址:https://blog.csdn.net/qq_23852555/article/details/126022332