您的位置:首页 > 其它

ACM集训日记-8月1日

2017-08-01 20:07 344 查看
    今天早上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;
}
这道题我上网看了昨天前辈们做的题解,感觉很精妙,下面是转载的加上我自己的理解(如果分析有误,请提出一并探讨!)

while(~scanf("%d%d%s",&n,&k,s)){  

                cnt=0;  

                for(i=0;i<26;i++) a[i]=b[i]=0;  

                for(i=0;s[i];i++) a[s[i]-'A']++;
//用数组a来标记在某个字母门进入的游客是否已经走完

                for(i=0;s[i];i++){
 //用数组b来标记每个字母门需要用到守卫的个数

                        if(!b[s[i]-'A']){  

                                cnt++;  

                                b[s[i]-'A']=1;  

                        }  

                        if(cnt>k){  

                                puts("YES");
 //如果需要的守卫大于已经有的守卫,那么说明需要增添守卫,然后跳出循环即可

                                break;  

                        }  

                        a[s[i]-'A']--;  

                        if(!a[s[i]-'A']){
 //如果一个门应该进去的游客已经走完那么正在执勤的守卫-1

                                cnt--;  

                        }  

                }  

                if(i==n) puts("NO"); 

    总的来说今天的收货还是蛮大的,每天意识到自己的不足,并有所改进,便是最大的进步!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: