codeforces 459C Pashmak and Buses 解题报告

题目链接:http://codeforces.com/problemset/problem/459/C

题目意思:有 n 个 students,k 辆 buses。问是否能对 n 个students安排每一天搭乘的buses,使得没有两个student 在 d 天搭乘相同的buses,buses 的 容量没有限制,也就是它可以搭无限多的人。

  做这条题的时候,我是得不出无解的条件的,看了 tutorial 之后一下子明白了,就是 k^d > n。很容易理解,因为每一天某个student可以选择的 buses 都有 k 种选择嘛~~~而且又因为要输出 d 行 n 列 那么多的数,所以 k ^ d > n 表示至少有两列数会使得某两个student 成为 close friend!

    知道这个之后就是如何构造答案了,其实就是所有排列情况,不过我是不会做啦~~~看了作者的代码自己重新写,非常惊叹他的智慧呀~~~

    拿这组数据来说吧,20   3   5

    

 

     结合代码中注释为transfer

   ans[i][j] = ans[i-1][j];  表示从左边那一列复制到下一列,那么为了不使得两个student成为close friend 就势必要使得他们有一点不同,这时就用到代码中的 update 操作了

     ans[i][j] = (ans[i][j] + 1) % k;   

     这行代码用得相当巧妙,由于循环是从 d-1 ——> 0 的,也就是对于当前处理的那一列,从下往上更改(如果遇到 % k == 0 的情况),否则(% k != 0)就在上一列的对应行 + 1。

     最后还有一个地方,在判断 k^d > n 的时候,如果可以提早发现有answer,要提早 break 出来,从 test7 可以知道!考虑数据范围:1 ≤ n, d ≤ 1000; 1 ≤ k ≤ 10^9 ,因为乘的时候有可能很大,超出long long 范围 !!

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 typedef long long LL;
 8 const int maxn = 1000 + 5;
 9 
10 int ans[maxn][maxn];
11 
12 int main()
13 {
14     #ifndef ONLINE_JUDGE
15         freopen("in.txt", "r", stdin);
16     #endif
17 
18     int n, k, d;
19     while (scanf("%d%d%d", &n, &k, &d) != EOF)
20     {
21         bool flag = false;
22         LL product = 1;
23         for (int i = 0; i < d; i++)
24         {
25              product *= (LL)k;     // one select has k choice
26              if (product >= n)      // mean has answer
27              {
28                  flag = true;
29                  break;
30              }
31         }
32 
33         if (!flag)      // repeat, no answer
34             printf("-1\n");
35         else            // construct the answer
36         {
37             memset(ans, 0, sizeof(ans));
38             for (int i = 1; i < n; i++)
39             {
40                 for (int j = 0; j < d; j++)
41                 {
42                     ans[i][j] = ans[i-1][j];   // right transfer
43                 }
44 
45                 for (int j = d-1; j >= 0; j--)   // update
46                 {
47                     ans[i][j] = (ans[i][j] + 1) % k;
48                     if (ans[i][j])
49                         break;
50                 }
51             }
52             for (int i = 0; i < d; i++)
53             {
54                 for (int j = 0; j < n; j++)
55                     printf("%d ", ans[j][i]+1);
56                 printf("\n");
57             }
58         }
59     }
60     return 0;
61 }

 

    

posted @ 2014-10-05 00:14  windysai  阅读(325)  评论(0编辑  收藏  举报