[关闭]
@morehigh 2017-05-27T15:45:02.000000Z 字数 3213 阅读 1001

CQUPT DP 2017/5/15

DP


B - XHXJ's LIS HDU - 4352

  1. 输入的L,R,K.(0<L<=R<2^63-1 and 1<=K<=10),表示一个数字拆分成位数(个,十,百。。)满足长度为K的递增的序列,求出从LR的满足条件的数字的个数。
  1. 数位dp+状态压缩,dp[pos][st][k]=ans,表示位数为pos,状态为st,上升子序列长度为k的个数为ans,其中用到位运算是为了解决上升序列状态,然后根据状态中1的个数可以算出上升序列的长度。
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. ll dp[50][1<<10][15];
  5. ll l,r,k;
  6. ll a[50];
  7. int getst(int st,int x)
  8. {
  9. for(int i=x;i<10;i++)
  10. if(st&(1<<i)) return ((st^(1<<i))|(1<<x));
  11. return st|(1<<x);
  12. }
  13. ll getlen(int st)
  14. {
  15. int cnt=0;
  16. while(st)
  17. {
  18. if(st&1) cnt++;
  19. st>>=1;
  20. }
  21. return cnt;
  22. }
  23. ll dfs(int pos,int st,int zero,int f)
  24. {
  25. if(pos<1) return getlen(st)==k;
  26. if(!f&&dp[pos][st][k]!=-1) return dp[pos][st][k];
  27. int las= f?a[pos]:9;
  28. ll ans=0;
  29. for(int i=0;i<=las;i++)
  30. {
  31. ans+=dfs(pos-1,(zero==0&&i==0)?0:getst(st,i),zero||i,f&&(i==las));
  32. }
  33. if(!f) dp[pos][st][k]=ans;
  34. return ans;
  35. }
  36. ll sol(ll x)
  37. {
  38. int len=0;
  39. while(x)
  40. {
  41. a[++len]=x%10;
  42. x/=10;
  43. }
  44. return dfs(len,0,0,1);
  45. }
  46. int main()
  47. {
  48. int t,cas=1;
  49. scanf("%d",&t);
  50. memset(dp,-1,sizeof(dp));
  51. while(t--)
  52. {
  53. scanf("%lld%lld%lld",&l,&r,&k);
  54. printf("Case #%d: %lld\n",cas++,sol(r)-sol(l-1));
  55. }
  56. return 0;
  57. }

C - Brackets Sequence POJ - 1141

  1. 左右括号匹配问题,给出一串字符,求出最少添加多少个括号,能使全部括号匹配,满足条件。
  1. d[i][j]表示在区间ij中有最少加多少个括号使得全部括号达到匹配,c[i][j]表示在ij中添加括号的位置,d[i][j]=min(d[i][j],d[i][k]+d[k+1][j]);
  2. if(ss[i]=='('&&ss[j]==')'||ss[i]=='['&&ss[j]==']') d[i][j]=d[i+1][j-1]; 区间ij暂时不用插入括号。
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <string>
  5. #include <algorithm>
  6. using namespace std;
  7. string ss;
  8. int len;
  9. int d[100][100];
  10. int c[100][100];
  11. void sol()
  12. {
  13. int mn,j;
  14. memset(d,0,sizeof(d));
  15. for(int i=0;i<len;i++) d[i][i]=1;
  16. for(int l=1;l<len;l++)
  17. {
  18. for(int i=0;i+l<len;i++)
  19. {
  20. j=i+l;
  21. d[i][j]= 0x7fffffff;
  22. for(int k=i;k<j;k++)
  23. {
  24. if(d[i][k]+d[k+1][j]<d[i][j])
  25. {
  26. d[i][j]=d[i][k]+d[k+1][j];
  27. c[i][j]=k;
  28. }
  29. }
  30. // d[i][j]=mn;
  31. if(ss[i]=='('&&ss[j]==')'||ss[i]=='['&&ss[j]==']')
  32. {
  33. if(d[i+1][j-1]<d[i][j])
  34. {
  35. d[i][j]=d[i+1][j-1];
  36. c[i][j]=-1;
  37. }
  38. }
  39. }
  40. }
  41. }
  42. void print(int i,int j)
  43. {
  44. if(i>j) return ;
  45. if(i==j)
  46. {
  47. if(ss[i]=='('||ss[i]==')') cout<<"()";
  48. else cout<<"[]";
  49. }else{
  50. if(c[i][j]>=0)
  51. {
  52. print(i,c[i][j]);
  53. print(c[i][j]+1,j);
  54. }
  55. else{
  56. if(ss[i]=='(')
  57. {
  58. cout<<"(";
  59. print(i+1,j-1);
  60. cout<<")";
  61. }else{
  62. cout<<"[";
  63. print(i+1,j-1);
  64. cout<<"]";
  65. }
  66. }
  67. }
  68. }
  69. int main()
  70. {
  71. cin>>ss;
  72. len =ss.size();
  73. sol();
  74. // cout<<d[0][len-1]<<endl;
  75. print(0,len-1);
  76. cout<<endl;
  77. return 0;
  78. }

E - Little Elephant and Elections

  1. 要在7个政党中进行选举,小象政党认为47是幸运数字,每个政党将被分配一个数字,若小象政党中幸运数字的个数大于其他6个政党幸运数字的个数,有多少中正确的分配方式满足条件。
  1. 首先确定第七个数的lucky值,然后分别枚举其他六个数的情况。确定了第七个数,我们就可以利用dfs深搜出每种符合条件的结果并且将结果加到ans中。
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int mod=1000000007;
  5. ll dp[20][20];
  6. ll res[20];
  7. int bit[20],num;
  8. ll ans;
  9. void DFS(ll now,int mx,int pt,ll cur)
  10. {
  11. if(now>=mx)//如果其他的lucky超过小象政党的lucky值,跳出
  12. return ;
  13. if(pt==7)
  14. {
  15. if(now<mx)
  16. {
  17. ans+=cur;
  18. ans%=mod;
  19. }
  20. return ;
  21. }
  22. for(int i=0;i<num;i++)
  23. {
  24. if(res[i])
  25. {
  26. res[i]--;
  27. DFS(now+i,mx,pt+1,cur*(res[i]+1)%mod);
  28. res[i]++;
  29. }
  30. }
  31. }
  32. ll dfs(ll pos,ll mx,ll limit)
  33. {
  34. ll sum=0;
  35. if(pos==0) return mx==0;
  36. if(limit==0&&dp[pos][mx]!=-1)
  37. return dp[pos][mx];
  38. ll las=limit?bit[pos]:9;
  39. for(int i=0;i<=las;i++)
  40. {
  41. sum+=dfs(pos-1,mx-(i==4||i==7),(limit==1&&bit[pos]==i));
  42. }
  43. if(!limit) dp[pos][mx]=sum;//位数为pos,lucky数为mx时的种类数
  44. return sum;
  45. }
  46. void col(ll m)
  47. {
  48. ans=num=0;
  49. ll y=m;
  50. while(y)
  51. {
  52. bit[++num]=y%10;
  53. y/=10;
  54. }
  55. for(int i=0;i<=num;i++)
  56. res[i]=dfs(num,i,1); //小象政党最多获得的lucky值为num,res[i]表示lucky值为i的数字的个数
  57. res[0]-=1;
  58. for(int i=1;i<=num;i++)
  59. DFS(0,i,1,res[i]); //当小象政党的lucky值为i时,其他6个政党的lucky和小于i的方案数
  60. }
  61. int main()
  62. {
  63. ll m;
  64. memset(dp,-1,sizeof(dp));
  65. scanf("%lld",&m);
  66. col(m);
  67. printf("%lld\n",ans);
  68. return 0;
  69. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注