ACM集训日记-8月1日

来源:互联网 发布:mac如何双开战网 编辑:程序博客网 时间:2024/09/21 06:15

    今天早上a了两道题,第一道题点击打开链接,第二道题点击打开链接,没有题解的帮助,就像是在深山老林里开荒一样,第四题棋盘问题一开始题目理解错了,题目描述是“在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。”一开始我理解成只要棋子不相邻即可,简直大错特错。

void dfs(int z)//这里的z就直接可以代表从第z行开始遍历,一行只放一个,判断是否同行就可以直接解决
{
    if(sum==k)//如果棋子数用了k个说明用完了,遍历结束
    {
        cnt++;
        return;
    }
    else
    {
        if(z>=n)return;
        else
        {
            for(int i=0;i<n;i++)//确定一行后,在从0到n-1列遍历,判断是否同列也可以直接解决
            {
                if(judge(z,i))
                {
                    vis[i]=1;
                    sum++;
                    dfs(z+1);
                    sum--;
                    vis[i]=0;
                }
            }
            dfs(z+1);//然后遍历z+1个棋子的情况
        }
    }
}

    这道题我一开始做出来怎么结果都是1,后来发现vis[i]=0;后面加了return!我真傻真的,这样sum++后就结束了sum一直都是1,简直傻的可以。

    第二道题我用的是强硬的办法,输进去一个数,一直算只包含1和0的数直到可以整除这个数就break出来,简直不要太暴力。就是还没看别人是怎么做的,晚上回去看看别人的题解吧。

    下午参加了暑假的第一次训练赛,虽然以前也参加过类似的,是codeforces上的比赛,最终结果是只做出了第一题,第二题胎死腹中,我们最好的是做出了两题,都是英文题目,读题难免有些障碍,第一题点击打开链接,还算好,不过我自己的问题,考虑不是很清楚第一次,用的有点呆呆的方法

#include<iostream>#include<cstdio>using namespace std;int main(){    int cw[7]={118,60,94,62,118,60,94};//为了后面的加法不会越界    int ccw[7]={118,62,94,60,118,62,94};    char a,b,c;    int t,i,f1=0,f2=0;    cin>>a;    c=getchar();    cin>>b;    cin>>t;    i=t%4;    for(int k=0;k<4;k++)    {        if(cw[k]==int(a))        {            if(cw[k+i]==int(b)){f1=1;break;}        }    }    for(int k=0;k<4;k++)    {        if(ccw[k]==int(a))        {            if(ccw[k+i]==int(b)){f2=1;break;}        }    }    if(f1==f2)cout<<"undefined";    else if(f1)cout<<"cw";         else if(f2)cout<<"ccw";    return 0;}

     最后判断顺时针还是逆时针的时候我忘记了转4次会回到原点从而无法判断的情况。

    第二道题点击打开链接,我就是被第二题磨死的,其实应该也不难,但是我就是一直在后面的某组数据超时了,因为我对每个字母都进行了搜索,超时好像也是没有办法的,这是我的代码:

#include<iostream>#include<vector>#include<cstdio>#include<string.h>#include <algorithm>using namespace std;int asc[135][2];int asc2[135];int main(){    int a,b,cnt=0,min,max;    char c;    char l[1000005];    cin>>a>>b;    for(int i=1;i<=a;i++)    {        //cin>>c;        scanf("%d",&c);        l[i]=c;    }    memset(asc,0,sizeof(asc));    memset(asc2,0,sizeof(asc2));    for(int i=1;i<=a;i++)    {        for(int j=1;j<i;j++)        {            if(l[j]!=l[i])asc[int(l[i])][0]=i;            else {asc[int(l[i])][0]=j;break;}        }        for(int k=a;k>i;k--)        {            if(l[k]!=l[i])asc[int(l[i])][1]=i;            else {asc[int(l[i])][1]=k;break;}        }    }    min=9999999;    max=0;    for(int i=65;i<=90;i++)//后面较大的数据,在这里就会超时!    {        for(int j=i+1;j<=90;j++)        {            if(asc[j][0]!=0&&asc[i][0]!=0)            {                if(asc[i][0]<asc[j][0]/*&&asc[i][0]<min*/)min=asc[j][0]/*min=asc[i][0]*/;                else if(asc[j][0]<min)min=asc[i][0];                if(asc[i][1]<asc[j][1]&&asc[j][1]>max)max=asc[j][1];                else if(asc[i][1]>max)max=asc[i][1];            }        }    }    //cout<<min<<max;    for(int i=min;i<=max;i++)    {        asc2[l[i]]++;    }    for(int i=65;i<=90;i++)    {        if(asc2[i]!=0)cnt++;    }    //cout<<cnt;    if(cnt>b)cout<<"YES";    else cout<<"NO";    return 0;}

这道题我上网看了昨天前辈们做的题解,感觉很精妙,下面是转载的加上我自己的理解(如果分析有误,请提出一并探讨!)

  1. while(~scanf("%d%d%s",&n,&k,s)){  
  2.                 cnt=0;  
  3.                 for(i=0;i<26;i++) a[i]=b[i]=0;  
  4.                 for(i=0;s[i];i++) a[s[i]-'A']++; //用数组a来标记在某个字母门进入的游客是否已经走完
  5.                 for(i=0;s[i];i++){  //用数组b来标记每个字母门需要用到守卫的个数
  6.                         if(!b[s[i]-'A']){  
  7.                                 cnt++;  
  8.                                 b[s[i]-'A']=1;  
  9.                         }  
  10.                         if(cnt>k){  
  11.                                 puts("YES");  //如果需要的守卫大于已经有的守卫,那么说明需要增添守卫,然后跳出循环即可
  12.                                 break;  
  13.                         }  
  14.                         a[s[i]-'A']--;  
  15.                         if(!a[s[i]-'A']){  //如果一个门应该进去的游客已经走完那么正在执勤的守卫-1
  16.                                 cnt--;  
  17.                         }  
  18.                 }  
  19.                 if(i==n) puts("NO"); 

    总的来说今天的收货还是蛮大的,每天意识到自己的不足,并有所改进,便是最大的进步!