近期总结_xdu 11月赛

  又见括号匹配

 赛后想到一个3维dp,f[i][j][k]表示第i个位置匹配j个')',剩余k个未匹配,为了保证匹配方式合法,即在任意位置往前看右括号数必须大于等于左括号数,"()((..."为合法"())((..."就不合法。0

 举了1个简单的例子 n=8时  " ( 1 ( 2 ( 3 ()"  即求将3个右括号合法地插入1,2,3,这3个位置的方案数。初始化f[3][j][k]=1;

 f[2][j][k]=sum(f[3][r][k-r])    0<=r<=t;  t=3-j-r && k-r>=0 这都是为了使括号的插入合法化(k-r>=0貌似不需要哈- -');

然后就是字符串匹配了.ans[i]表示第i个位置匹配的左括号数,第n/2个位置的匹配数为n/2-前面所有的匹配数。

关键代码

 for(i=1,k=n/2-1;i<=n/2-1;i++)

 {

    for(j=0;j<=i;j++)

    {

      k-=j;

      rest_k=k;

      ans[i]=j;

      if(f[i][j][rest_k]<seq)seq-=f[i][j][rest_k];

      else  break;

      k+=j;

      ans[i]=0;

    }

 }

 

 打牌

 背包问题。有n种物品,每种有m个,可以转化为有n*m种物品的背包,但是m和n比较大,这么写必定会超时。

 在这里学到一个2进制优化,也就是说不必转化为n*m个物品的背包,而是转化成n*lgm个物品  (0001)2表示取1个(0010)2表示取2个......决策中取3个被0001+0010代替,

 这个办法太飘逸了,而且很有用的样子......之后用滚动数组优化空间就ok了。

 

 帧爷的苹果

 配对问题,只是数据有点大。朴素的算法是

 

View Code
for(i=0;i<n;i++)

 {

    for(j=i;j<n;j++)

    if(seq[i]+seq[j]==m)count++;

 }

这是O(n^2)的 必定会超时。可以用字典树把查找过程的复杂度降为常数。

View Code
for(i=0;i<n;i++)

{

  num=m-seq[i];

  count_i=find(seq[i]);//在字典树中找到seq[i]的个数

  count_j=find(num);//找到num的个数

  count+=count_i * count_j;//统计方案数,要注意seq[i]=num的情况...懒得写了- -'

  clear(seq[i]);clear(num);//配对后清0避免重复统计,这里要注意 不清零而在最后/2 是有bug的 因为seq[i]=num的情况特殊考虑了......

}

 罪恶的王冠

 讨论多元方程解的问题,第一次提交 试图根据约束条件剪枝+搜索,严重超时啊T T...... 后来看了解答,发现关键在于构造解, 讨论输入数据的关系,会发现在某些条件下无法构造解,即无解,输出'Error';在某些条件下有一个明显的解,且无法另外构造出一个解,即1解的情况,这种情况需要输出解;在某些情况下,还能构造出另一个解,此时输出multipe.

 wiki上给的解答貌似有些笔误......- -.

 

 帧爷的生日

 背景是道著名的智力问题,读完题,费了好长时间才知道,这题模拟就可以了,用2个2维数组来列举2个人的信息,按步骤筛去一些,最后输出没有筛去的。

 有个小小的wa点.

View Code
 1 #include<stdio.h>
2 #include<string.h>
3
4 char g_m[13][32];
5 char g_q[32][13];
6
7 int input()
8 {
9 int i,j,m,d;
10 for(i=0;i<33;i++)
11 for(j=0;j<33;j++)
12 g_q[i][j]=g_m[i][j]='0';
13 for(i=0;i<10;i++)
14 {
15 if(scanf("%d.%d",&m,&d)==EOF)return 0;
16 g_m[m][d]=1+'0';
17 g_q[d][m]=1+'0';
18 }
19 return 1;
20 }
21 void work()
22 {
23 int i,j,k,count,tmp;
24 char tmp_q[32][13],tmp_m[13][32];
25 //wa点1:要用一个tmp来临时存放g
26 memcpy(tmp_q,g_q,sizeof(g_q));

27 memcpy(tmp_m,g_m,sizeof(g_m));
28 for(i=1;i<=31;i++)
29 {
30 for(j=1,count=0;j<=12;j++)
31 if(tmp_q[i][j]!='0'){count++;tmp=j;}
32 if(count==1)
33 {
34 for(k=1;k<=31;k++)
35 {
36 g_q[k][tmp]='0';
37 g_m[tmp][k]='0';
38 }
39 }
40 }
41 memcpy(tmp_q,g_q,sizeof(g_q));
42 memcpy(tmp_m,g_m,sizeof(g_m));
43 for(i=1;i<=31;i++)
44 {
45 for(j=1,count=0;j<=12;j++)
46 if(tmp_q[i][j]!='0')count++;
47 if(count>1)
48 {
49 for(k=1;k<=12;k++)
50 {
51 g_m[k][i]='0';
52 g_q[i][k]='0';
53 }
54 }
55 }
56 memcpy(tmp_q,g_q,sizeof(g_q));
57 memcpy(tmp_m,g_m,sizeof(g_m));
58 for(i=1;i<=12;i++)
59 {
60 for(j=1,count=0;j<=31;j++)
61 if(tmp_m[i][j]!='0')count++;
62 if(count>1)
63 {
64 for(k=1;k<=31;k++)
65 {
66 g_m[i][k]='0';
67 g_q[k][i]='0';
68 }
69 }
70 }
71 for(i=1;i<=12;i++)
72 for(j=1;j<=31;j++)
73 if(g_m[i][j]!='0')
74 {
75 printf("%d.%d\n",i,j);
76 return;
77 }
78 }
79 int main()
80 {
81 freopen("ph.txt","r",stdin);
82 while(input())
83 {
84 work();
85 }
86 return 0;
87 }

 

转载于:https://www.cnblogs.com/eggeek/archive/2011/12/10/2283073.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值