CF 222 (DIV 1)

A:

我是bfs出一颗树,然后删掉树后面的k个结点。

其实也可以直接bfs出一块连通的s - k个点,其余的.打X就可以了。

很水的题目。

 1 /* ***********************************************

 2 Author        :kuangbin

 3 Created Time  :2013-12-29 23:26:26

 4 File Name     :E:\2013ACM\CF比赛\CF222\A.cpp

 5 ************************************************ */

 6 

 7 #include <stdio.h>

 8 #include <string.h>

 9 #include <iostream>

10 #include <algorithm>

11 #include <vector>

12 #include <queue>

13 #include <set>

14 #include <map>

15 #include <string>

16 #include <math.h>

17 #include <stdlib.h>

18 #include <time.h>

19 using namespace std;

20 char str[550][550];

21 bool vis[550][550];

22 int n,m,k;

23 pair<int,int> p[510*510];

24 int cnt;

25 int Move[][2] = {{0,1},{0,-1},{1,0},{-1,0}};

26 queue<pair<int,int> >q;

27 void bfs(int x0,int y0)

28 {

29     memset(vis,false,sizeof(vis));

30     cnt = 0;

31     while(!q.empty())q.pop();

32     q.push(make_pair(x0,y0));

33     vis[x0][y0] = true;

34     p[cnt++] = make_pair(x0,y0);

35     while(!q.empty())

36     {

37         pair<int,int> tmp = q.front();

38         q.pop();

39         for(int i = 0;i < 4;i++)

40         {

41             int x = tmp.first + Move[i][0];

42             int y = tmp.second + Move[i][1];

43             if(x < 0 || y < 0 || x >= n || y >= m)continue;

44             if(vis[x][y])continue;

45             if(str[x][y] ==  '#')continue;

46             p[cnt++] = make_pair(x,y);

47             vis[x][y] = true;

48             q.push(make_pair(x,y));

49         }

50     }

51 }

52 

53 int main()

54 {

55     //freopen("in.txt","r",stdin);

56     //freopen("out.txt","w",stdout);

57     while(cin>>n>>m>>k)

58     {

59         for(int i = 0;i < n;i++)

60             scanf("%s",str[i]);

61         int x0 , y0 = -1;

62         for(int i = 0;i < n;i++ )

63         {

64             if(y0 != -1)break;

65             for(int j = 0;j < m;j++)

66                 if(str[i][j] == '.')

67                 {

68                     x0 = i;y0 = j;

69                     break;

70                 }

71         }

72         bfs(x0,y0);

73         for(int i = 0;i < k;i++)

74         {

75             int x = p[cnt-1-i].first;

76             int y = p[cnt-1-i].second;

77             str[x][y] = 'X';

78         }

79         for(int i = 0;i < n;i++)

80             cout<<str[i]<<endl;

81     }

82     return 0;

83 }

 

 

 

B:

题目很长,自己看吧!

 

使用二分+判断就可以了。复杂度大概是n * log(10^9)*log(n).

 

二分天数,在1~m 的范围二分。

天数为mid天时候,判断。按照a的大小,从大到小,在满足b>=a的里面,找出一个c最小的,然后连续删掉mid个a.

最后判断总价。

使用优先队列写的,用set也可以。

  1 /* ***********************************************

  2 Author        :kuangbin

  3 Created Time  :2013-12-29 23:57:57

  4 File Name     :E:\2013ACM\CF比赛\CF222\B.cpp

  5 ************************************************ */

  6 

  7 #include <stdio.h>

  8 #include <string.h>

  9 #include <iostream>

 10 #include <algorithm>

 11 #include <vector>

 12 #include <queue>

 13 #include <set>

 14 #include <map>

 15 #include <string>

 16 #include <math.h>

 17 #include <stdlib.h>

 18 #include <time.h>

 19 using namespace std;

 20 const int MAXN = 100010;

 21 int a[MAXN];

 22 int b[MAXN];

 23 int c[MAXN];

 24 int n,m,s;

 25 

 26 struct node

 27 {

 28     int x, y;

 29     int index;

 30     friend bool operator < (node a, node b)

 31     {

 32         return a.y > b.y; //结构体中,y小的优先级高

 33     }

 34 };

 35 priority_queue<node>q;

 36 

 37 //适用于正负整数

 38 template <class T>

 39 inline bool scan_d(T &ret) {

 40    char c; int sgn;

 41    if(c=getchar(),c==EOF) return 0; //EOF

 42    while(c!='-'&&(c<'0'||c>'9')) c=getchar();

 43    sgn=(c=='-')?-1:1;

 44    ret=(c=='-')?0:(c-'0');

 45    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');

 46    ret*=sgn;

 47    return 1;

 48 }

 49 

 50 node nn[MAXN];

 51 bool cmp(node a,node b)

 52 {

 53     return a.x > b.x;

 54 }

 55 int AA[MAXN];

 56 bool cmp11(int t1,int t2)

 57 {

 58     return a[t1] > a[t2];

 59 }

 60 int BB[MAXN];

 61 

 62 bool check(int pp)

 63 {

 64     while(!q.empty())q.pop();

 65     int i = 0,j = 0;

 66     long long ret = 0;

 67     while(i < m)

 68     {

 69         while(j < n && nn[j].x >= a[i])

 70         {

 71             q.push(nn[j]);

 72             j++;

 73         }

 74         if(q.empty())return false;

 75         node tmp = q.top();

 76         q.pop();

 77         ret += tmp.y;

 78         if(ret > s)return false;

 79         int ccc = pp;

 80         while(ccc && i < m)

 81         {

 82             ccc--;

 83             BB[AA[i]] = tmp.index;

 84             i++;

 85         }

 86     }

 87     return true;

 88 }

 89 

 90 

 91 int main()

 92 {

 93     //freopen("in.txt","r",stdin);

 94     //freopen("out.txt","w",stdout);

 95     while(scanf("%d%d%d",&n,&m,&s) == 3)

 96     {

 97         for(int i = 0;i < m;i++)

 98         {

 99             scan_d(a[i]);

100         }

101         for(int i = 0;i < n;i++)

102             scan_d(b[i]);

103         for(int i = 0;i < n;i++)

104             scan_d(c[i]);

105         for(int i = 0;i < m;i++)

106             AA[i] = i;

107         sort(AA,AA+m,cmp11);

108         sort(a,a+m);

109         reverse(a,a+m);

110         for(int i = 0;i < n;i++)

111         {

112             nn[i].x = b[i];

113             nn[i].y = c[i];

114             nn[i].index = i+1;

115         }

116         sort(nn,nn+n,cmp);

117         if(check(m) == false)

118         {

119             printf("NO\n");

120             continue;

121         }

122         int l = 1, r = m;

123         int ans;

124         while(l <= r)

125         {

126             int mid = (l + r)/2;

127             if(check(mid))

128             {

129                 ans = mid;

130                 r = mid -1;

131             }

132             else l = mid+1;

133         }

134         check(ans);

135         printf("YES\n");

136         for(int i = 0;i  < m;i++)

137         {

138             printf("%d",BB[i]);

139             if(i < m-1)printf(" ");

140             else printf("\n");

141         }

142     }

143     return 0;

144 }

 

 

 

 

C:

比较有意思的题目。

其实s数组从大到小排序以后,只和前m大的数有关的,后面的无关。

m<=20

一种是复杂度为 m * m * 2^m 的算法,虽然复杂度比较大,可以勉强在CF上跑过去。

使用dp[20][1<<20],  dp[i][j] 表示前m个s数组存在情况为j时候,处理到第i步。

答案就是dp[0][(1<<m)-1]

然后就是枚举当前步是取哪一个,或者去掉哪一个,或者忽略这个操作。

代码如下(不建议看,复杂度大)

CF 222 (DIV 1)
 1 /* ***********************************************

 2 Author        :kuangbin

 3 Created Time  :2013-12-30 1:06:58

 4 File Name     :E:\2013ACM\CF比赛\CF222\C.cpp

 5 ************************************************ */

 6 

 7 #include <stdio.h>

 8 #include <string.h>

 9 #include <iostream>

10 #include <algorithm>

11 #include <vector>

12 #include <queue>

13 #include <set>

14 #include <map>

15 #include <string>

16 #include <math.h>

17 #include <stdlib.h>

18 #include <time.h>

19 using namespace std;

20 const int INF = 0x3f3f3f3f;

21 

22 int s[110];

23 int n,m;

24 struct Node

25 {

26     char op[10];

27     int id;

28 };

29 Node node[100];

30 bool used[100];

31 int a[100];

32 int cnt;

33 int dp[22][1<<20];

34 int loc[1<<22];

35 

36 int bit[22];

37 int main()

38 {

39     //freopen("in.txt","r",stdin);

40     //freopen("out.txt","w",stdout);

41     for(int i = 0;i <= 21;i++)

42         loc[1<<i] = i;

43     for(int i = 0;i < 22;i++)

44         bit[i] = 1<<i;

45     while(cin>>n)

46     {

47         for(int i = 0;i < n;i++)

48             cin>>s[i];

49         sort(s,s+n);

50         reverse(s,s+n);

51         cnt = 0;

52         scanf("%d",&m);

53         for(int i = 0;i < m;i++)

54         {

55             scanf("%s%d",node[i].op,&node[i].id);

56         }

57         int tot = (1<<m);

58         memset(dp,0,sizeof(dp));

59         for(int i = m-1;i >= 0;i--)

60             for(int j = 0;j < tot;j++)

61             {

62                 if(j == 0)

63                 {

64                     continue;

65                 }

66                 if(node[i].id == 1)dp[i][j] = -INF;

67                 else dp[i][j] = INF;

68                 for(int id  = 0;id < m;id++)

69                 {

70                     if((j & bit[id]) == 0)continue;

71 

72                     if(node[i].id == 1)

73                     {

74                         if(node[i].op[0] == 'p')

75                             dp[i][j] = max(dp[i][j],max(dp[i+1][j],dp[i+1][j ^ bit[id]] + s[id]));

76                         else dp[i][j] = max(dp[i][j],max(dp[i+1][j],dp[i+1][j ^ bit[id]]));

77                     }

78                     else

79                     {

80                     

81                         if(node[i].op[0] == 'p')

82                             dp[i][j] = min(dp[i][j],min(dp[i+1][j],dp[i+1][j ^ bit[id]] - s[id]));

83                         else dp[i][j] = min(dp[i][j],min(dp[i+1][j],dp[i+1][j ^ bit[id]]));

84                     }

85                 }

86             }

87         printf("%d\n",dp[0][tot-1]);

88     }

89     return 0;

90 }
View Code

 

 

其实操作根本不会被忽略,每一步肯定要操作的。

所以状态可以减少一维,直接dp[i], 根据i中多少个0,就知道取了多少个了。

这样复杂度降为 m * 2^m

 

写起来也很方便

 1 /* ***********************************************

 2 Author        :kuangbin

 3 Created Time  :2013-12-30 2:22:12

 4 File Name     :E:\2013ACM\CF比赛\CF222\CC.cpp

 5 ************************************************ */

 6 

 7 #include <stdio.h>

 8 #include <string.h>

 9 #include <iostream>

10 #include <algorithm>

11 #include <vector>

12 #include <queue>

13 #include <set>

14 #include <map>

15 #include <string>

16 #include <math.h>

17 #include <stdlib.h>

18 #include <time.h>

19 using namespace std;

20 

21 const int INF = 0x3f3f3f3f;

22 int s[110];

23 int n,m;

24 struct Node

25 {

26     char op[10];

27     int id;

28 }node[22];

29 int dp[1<<20];

30 bool vis[1<<20];

31 

32 int solve(int st)

33 {

34     if(vis[st])return dp[st];

35     vis[st] = true;

36     int cnt = 0;

37     for(int i = 0;i < m;i++)

38         if((st & (1<<i)) == 0)

39             cnt++;

40     if(st == 0)return dp[st] = 0;

41     if(node[cnt].id == 1)

42     {

43         dp[st] = -INF;

44         for(int i = 0;i < m;i++)

45             if(st & (1<<i))

46             {

47                 if(node[cnt].op[0] == 'p')

48                     dp[st] = max(dp[st],solve(st ^ (1<<i)) + s[i]);

49                 else dp[st] = max(dp[st],solve(st ^ (1<<i)));

50             }

51     }

52     else

53     {

54         dp[st] = INF;

55         for(int i = 0;i < m;i++)

56             if(st & (1<<i))

57             {

58                 if(node[cnt].op[0] == 'p')

59                     dp[st] = min(dp[st],solve(st ^ (1<<i)) - s[i]);

60                 else dp[st] = min(dp[st],solve(st ^ (1<<i)));

61             }

62     }

63     return dp[st];

64 }

65 

66 int main()

67 {

68     //freopen("in.txt","r",stdin);

69     //freopen("out.txt","w",stdout);

70     while(cin>>n)

71     {

72         for(int i = 0;i < n;i++)

73             cin>>s[i];

74         sort(s,s+n);

75         reverse(s,s+n);

76         cin>>m;

77         for(int i = 0;i < m;i++)

78             scanf("%s%d",node[i].op,&node[i].id);

79         memset(vis,false,sizeof(vis));

80         printf("%d\n",solve((1<<m) - 1));

81     }

82     return 0;

83 }

 

 

 

 

 

D  :

待补中 

 

 

E:

待补中

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(div)