2018.10.07模拟总结

国庆5天乐在今天终于结束了,怀着明天又得上学的心情,我开始写这篇题解。

 

T1 wzoi

  期望得分:100

  实际得分:100

  首先题面非常的迷,我看了十分钟都没懂,看完T2,T3后再回来看T1,总共看题看了20分钟才懂……

  我发现最优的答案一定是回文串,那么ans = 10 * (len / 2),于是为了维护这个,我就开了个栈,如果栈是空的或者栈顶元素和当前数字不同,就放入栈,否则就把栈顶元素弹出,加10分。最后栈中要么不剩,要么一定是偶数个,加上5 * num / 2即可。

  总的来说就是贪心,正确性其实我也不太确定,但是手出的数据都过了……

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 1e6 + 5;
21 inline ll read()
22 {
23     ll ans = 0;
24     char ch = getchar(), last = ' ';
25     while(!isdigit(ch)) {last = ch; ch = getchar();}
26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
27     if(last == '-') ans = -ans;
28     return ans;
29 }
30 inline void write(ll x)
31 {
32     if(x < 0) x = -x, putchar('-');
33     if(x >= 10) write(x / 10);
34     putchar(x % 10 + '0');
35 }
36 void MYFILE()
37 {
38 #ifndef mrclr
39   freopen("wzoi.in", "r", stdin);
40   freopen("wzoi.out", "w", stdout);
41 #endif
42 }
43 
44 int n;
45 char c[maxn];
46 int a[maxn];
47 int st[maxn], sc = 0;
48 int ans = 0;
49 
50 int main()
51 {
52   MYFILE();
53   scanf("%s", c + 1);
54   n = strlen(c + 1);
55   for(int i = 1; i <= n; ++i) a[i] = c[i] - '0';
56   for(int i = 1; i <= n; ++i)
57     {
58       if(!sc || st[sc] != a[i]) st[++sc] = a[i];
59       else ans += 10, sc--;
60     }
61   if(sc) ans += 5 * (sc >> 1);
62   write(ans); enter;
63   return 0;
64 }
View Code

 

T2 course

  期望得分:10

  实际得分:40

  这题实在不会,开始搞10%的暴力:枚举全排列,然后判断是否合法,如果合法,在O(nm)判断单词是否是一个子串,记录个数。复杂度O(n! * n2 * m)。

  对于大的数,固输0.000000.

  然后成绩下来后也是惊了:0的点竟然有三个,净赚30.

  标程说出来可能不信:随机 +暴力判断。按题中描述可知,这些点构成一个森林,然后对于每一层的拓扑序,直接随机选哪个根节点,这样就得到了一个序列,剩下的就和暴力一样了。

  Ssy大佬直接随机序列,连判断都没有,竟然期望得分80~100……果然tql。

放一个考场40分的代码吧

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 20;
21 inline ll read()
22 {
23     ll ans = 0;
24     char ch = getchar(), last = ' ';
25     while(!isdigit(ch)) {last = ch; ch = getchar();}
26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
27     if(last == '-') ans = -ans;
28     return ans;
29 }
30 inline void write(ll x)
31 {
32     if(x < 0) x = -x, putchar('-');
33     if(x >= 10) write(x / 10);
34     putchar(x % 10 + '0');
35 }
36 void MYFILE()
37 {
38 #ifndef mrclr
39   freopen("course.in", "r", stdin);
40   freopen("course.out", "w", stdout);
41 #endif
42 }
43 
44 int n, m, pre[maxn], t[maxn];
45 char c[maxn], no[6][21], New[maxn];
46 bool vis[maxn];
47 
48 bool judge()
49 {
50   for(int i = 1; i <= n; ++i) vis[i] = 0;
51   vis[0] = 1;
52   for(int i = 1; i <= n; ++i)
53     {
54       if(!vis[pre[t[i]]]) return 0;
55       vis[t[i]] = 1;
56       New[i] = c[t[i]];
57     }
58   return 1;
59 }
60 void work0()
61 {
62   int tot = 0, totno = 0;
63   do
64     {
65       if(judge())
66     {
67       tot++;
68       for(int i = 1; i <= m; ++i)
69         {
70           bool flg = 0;
71           int l = strlen(no[i] + 1);
72           for(int j = 1; j <= n - l + 1; ++j)
73         {
74           bool flg2 = 1;
75           for(int k = 1; k <= l; ++k)
76             if(New[j + k - 1] != no[i][k]) {flg2 = 0; break;}
77           if(flg2) {flg = 1; break;}
78         }
79           if(flg) {totno++; break;}
80         }
81     }
82     }while(next_permutation(t + 1, t + n + 1));
83   printf("%.6lf\n", (db)(tot - totno) / (db)tot);
84 }
85 
86 int main()
87 {
88   MYFILE();
89   n = read();
90   if(n > 18) {printf("0.000000\n"); return 0;}
91   for(int i = 1; i <= n; ++i) pre[i] = read(), t[i] = i;
92   scanf("%s", c + 1);
93   m = read();
94   for(int i = 1; i <= m; ++i) scanf("%s", no[i] + 1);
95   work0();
96   return 0;
97 }
View Code

 

T3 painting

  期望得分:40

  实际得分:30

  这噶的更不会了!

  不过40分暴力想想还是能写出来的:把bfs的队列改成优先队列,每一次都从当前已经算出的最小的数向四个方向延伸,而且延伸出来的一定是w + d(w == wmin),因为对于任意一个w,一定有w + d >= wmin + d,说明这个点一定不是限制上限的点,为了最大化ans,就取w + d。

  丢了10分是因为没开long, long。(太zz了……)  

正解:没看懂。

40分代码

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<vector>
 9 #include<stack>
10 #include<queue>
11 using namespace std;
12 #define enter puts("") 
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 1e3 + 5;
21 const ll mod = 1e9 + 7;
22 inline ll read()
23 {
24     ll ans = 0;
25     char ch = getchar(), last = ' ';
26     while(!isdigit(ch)) {last = ch; ch = getchar();}
27     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
28     if(last == '-') ans = -ans;
29     return ans;
30 }
31 inline void write(ll x)
32 {
33     if(x < 0) x = -x, putchar('-');
34     if(x >= 10) write(x / 10);
35     putchar(x % 10 + '0');
36 }
37 void MYFILE()
38 {
39 #ifndef mrclr
40   freopen("painting.in", "r", stdin);
41   freopen("painting.out", "w", stdout);
42 #endif
43 }
44 
45 int n, m, k, d;
46 ll mp[maxn][maxn], ans = 0;
47 
48 const int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
49 struct Node
50 {
51   int x, y;
52   ll w;
53   bool operator < (const Node &oth)const
54   {
55     return w > oth.w;
56   }
57 };
58 priority_queue<Node> q;
59 void bfs()
60 {
61   while(!q.empty())
62     {
63       Node now = q.top(); q.pop();
64       ans += now.w; ans %= mod;
65       for(int i = 0; i < 4; ++i)
66     {
67       int newx = now.x + dx[i], newy = now.y + dy[i];
68       if(newx > 0 && newx <= n && newy > 0 && newy <= m)
69         {
70           if(mp[newx][newy])
71         {
72           if(mp[newx][newy] > now.w + d)
73             {printf("IMPOSSIBLE\n"); return;}
74         }
75           else
76         {
77           mp[newx][newy] = now.w + d;
78           q.push((Node){newx, newy, now.w + d});
79         }
80         }
81     }
82     }
83   write(ans); enter;
84 }
85 
86 int main()
87 {
88   MYFILE();
89   n = read(); m = read(); k = read(); d = read();
90   if(n > 1000 || m > 1000) {printf("IMPOSSIBLE\n"); return 0;}
91   for(int i = 1; i <= k; ++i)
92     {
93       int x = read(), y = read(), w = read();
94       mp[x][y] = w;
95       q.push((Node){x, y, w});
96     }
97   bfs();
98   return 0;
99 }
View Code

 

总结一下:第一题送的,剩下两题暴力+固输 = 40 + 40,所以今天应该180起……

posted @ 2018-10-07 15:48  mrclr  阅读(244)  评论(0编辑  收藏  举报