今天的比赛。

今天的比赛做的很纠结,该反思一下自己为什么做的这么烂了,约瑟夫环的那个问题,反映出自己掌握知识不够全面,只要我们知道那个证明实现起来就很轻松了,可是如果不知道的话就会被卡了。Run Length Encoding 这道题题意读的很是晕,迷迷糊糊就把代码完了,自己还出了好几组数据测试都过,一交还是wa,原来自己把题意理解错了,其实这道题的叙述真的很理解的。All Discs Considered 这道题没读懂题意,自己猜的是拓扑排序,可是比赛时卡到那几个题了所以就没写,后来自己读了几遍题意,想了想还是不知道该怎么写,最后还是搜了一下解题报告才出来的。。。就看了这几道题。。。

1:自己的知识面太狭隘;2:读题不认真;3:思路不清晰,不敢写。。。唉.......以后要注意了。

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2348 

这道题的题意是有两个磁盘,第一个磁盘有n1个安装包,(1--n1)第二个磁盘有n2个安装包(n1 + 1,n1 + n2),还有就是有d个依赖关系,x y x在只有y安装成功的前提下才能安装。每次安装只能安装同一个磁盘下的安装包。如果接下来的安装包和上一个不属于同一个磁盘,那么就需要改变一次,求最小改变次数。

拓扑排序,用两个队列来存储两个磁盘要处理的安装包,分先处理n1 和先处理 n2 两种情况求最小值。

View Code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#define maxn 100007
using namespace std;

int d[maxn],td[maxn];
int n1,n2,dx;

struct node
{
    int v;
    int next;
}e[maxn];
int p[maxn],len;
void init()
{
    int i;
    for (i = 0; i < maxn; ++i)
    {
        p[i] = -1; d[i] = td[i] = 0;
    }
    len = 0;
}
void insert(int x,int y)
{
    e[len].v = y;
    e[len].next = p[x];
    p[x] = len++;
}
int topsort(int mk)
{
    int i;
    int ct = 1;
    queue<int>q[2];
    for (i = 1; i <= n1 + n2; ++i)
    {
        if (td[i] == 0)
        {
            if (i <= n1) q[0].push(i);
            else q[1].push(i);
        }
    }
    while (!q[mk].empty() || !q[mk^1].empty())
    {
        while (!q[mk].empty())
        {
            int cur = q[mk].front(); q[mk].pop();
            for (i = p[cur]; i != -1; i = e[i].next)
            {
                int pos = e[i].v;
                td[pos]--;
                if (td[pos] == 0)
                {
                    if (pos <= n1) q[0].push(pos);
                    else           q[1].push(pos);
                    td[pos] = -1;
                }
            }
        }
        //mk磁盘中无可处理安装包了
        ct++; mk ^= 1;
    }
    return ct;
}
int main()
{
   int i,x,y;
   while (scanf("%d%d%d",&n1,&n2,&dx))
   {
       if (!n1 && !n2 && !dx) break;
       init();
       for (i = 0; i < dx; ++i)
       {
           scanf("%d%d",&x,&y);
           insert(y,x);
           d[x]++;
       }
       for (i = 1; i <= n1 + n2; ++i) td[i] = d[i];
       int l = topsort(0);
       for (i = 1; i <= n1 + n2; ++i) td[i] = d[i];
       int r = topsort(1);
       printf("%d\n",min(l,r));
   }
   return 0;
}

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2351

考察约瑟夫环的优化问题 http://baike.baidu.com/view/717633.htm

m等于2时有公式n=2^m+lhttp://zh.wikipedia.org/wiki/%E7%BA%A6%E7%91%9F%E5%A4%AB%E6%96%AF%E9%97%AE%E9%A2%98

View Code
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

char str[5];
int main()
{
   while (scanf("%s",str))
   {
       int a;
       if (!strcmp(str,"00e0")) break;
       int num = 0;
       num = num*10 + str[0] - '0';
       num = num*10 + str[1] - '0';
       int len = str[3] - '0';
       for (int i = 0; i < len; ++i) num *= 10;
       for (a = 1; a < num; a *= 2)
       {
           if (num - a < a) break;
       }
       printf("%d\n",2*(num - a) + 1);
   }
    return 0;
}

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2352

题目描述很操蛋。。。

就是如果出现连续的字符输出其个数以及该字符,如果大于9个只处理前九个,后面的按新的字符串处理,如果不连续,首先输出1然后输出不连续的字符序列最后在输出1 如果不连续的字符序列中有1则输出11

注意当输入字符只有1是输出1111

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 1007
using namespace std;

char str[maxn];

int main()
{
    //freopen("in.txt","r",stdin);
    int i,j;
   while (gets(str) != NULL)
   {
       int len = strlen(str);
       str[len] = '\0';
       //一个是单独处理一下
       if (len == 1)
       {
           if (str[0] == '1') printf("1111\n");
           else printf("1%c1\n",str[0]);
           continue;
       }
       for (i = 0; i < len;)
       {
           if (str[i] == str[i + 1])
           {
               //把连续的先输出
               int ct = 0;
               for (j = i; str[j] == str[j + 1] && ct < 8; ++j,++ct)
               {}
               printf("%d%c",ct + 1,str[i]);
               i = j + 1;
           }
           else
           {
               //不连续的首先输出1
               printf("1");
               for (j = i; str[j] != str[j + 1]; ++j)
               {}
              // printf(">>>%d\n",j);
               for (int p = i; p < j; ++p)
               {
                   //如果有1输出11
                   if (str[p] == '1')
                   printf("11");
                   else
                   printf("%c",str[p]);
               }
               printf("1");
               i = j;
           }
       }
       printf("\n");
       memset(str,0,sizeof(str));
   }
    return 0;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值