[2019HDU多校第一场][HDU 6578][A. Blank]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6578

题目大意:长度为\(n\)的数组要求分别填入\(\{0,1,2,3\}\)四个数中的任意一个,有\(m\)个限制条件:区间\([l,r]\)中出现的数字种数恰好为\(x\),求方案数

题解:f[i][j][k][cur]表示四个数最后出现的位置经过排序后为\(i,j,k,cur\)的方案数,暴力转移即可,其中最后一维需要滚动数组节省空间

   对于限制条件可以用vector存下来,每次循环对右端点为当前点的限制条件进行判断即可

   虽然要套四个\(for\),但是由于有顺序限制,所以执行次数大约为\(\frac{n^4}{24}\),加上本题的运算简单,常数较小,因此基本不会出现TLE的情况

 

   但是还是要吐槽一句出题人把这场比赛的时间设的好死啊...开个3s应该也不至于放假算法过吧orz

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 101
 4 #define mp make_pair
 5 #define MOD 998244353
 6 int T,n,m,l,r,x,f[N][N][N][2],ans;
 7 vector<pair<int,int>>d[N];
 8 void init()
 9 {
10     ans=0;
11     scanf("%d%d",&n,&m);
12     for(int i=1;i<=n;i++)
13       {
14       d[i].clear();
15       d[i].push_back(mp(i,1));
16       }
17     for(int i=1;i<=m;i++)
18       {
19       scanf("%d%d%d",&l,&r,&x);
20       d[r].push_back(mp(l,x));
21       }
22     memset(f,0,sizeof(f));
23     f[0][0][0][0]=1;
24     for(int cur=1;cur<=n;cur++)
25       {
26       int o=cur&1;
27       for(int i=0;i<=cur;i++)
28         for(int j=i;j<=cur;j++)
29           for(int k=j;k<=cur;k++)
30             f[i][j][k][o]=0;
31       for(int i=0;i<=cur;i++)
32         for(int j=i;j<=cur;j++)
33           for(int k=j;k<=cur;k++)
34             {
35             (f[j][k][cur-1][o]+=f[i][j][k][o^1])%=MOD;
36             (f[i][k][cur-1][o]+=f[i][j][k][o^1])%=MOD;
37             (f[i][j][cur-1][o]+=f[i][j][k][o^1])%=MOD;
38             (f[i][j][k][o]+=f[i][j][k][o^1])%=MOD;
39             }
40       for(int i=0;i<=cur;i++)
41         for(int j=i;j<=cur;j++)
42           for(int k=j;k<=cur;k++)
43             for(auto pi:d[cur])
44               {
45               l=pi.first,r=cur,x=pi.second;
46               if((i>=l)+(j>=l)+(k>=l)+(cur>=l)!=x)
47                 f[i][j][k][o]=0;
48               }
49       }
50     for(int i=0;i<=n;i++)
51       for(int j=i;j<=n;j++)
52         for(int k=j;k<=n;k++)
53           (ans+=f[i][j][k][n&1])%=MOD;
54     printf("%d\n",ans);
55 }
56 int main()
57 {
58     scanf("%d",&T);
59     while(T--)init();
60 }
View Code

代码中对vector的初始化其实是没必要额外push_back的,写的时候为了保险就加上去了(虽然差点导致TLE)

 

这竟然是我博客里的第一道纯DP题...?

posted @ 2019-07-23 00:51  DeaphetS  阅读(1099)  评论(3编辑  收藏  举报