NOIP2015 day1[tarjan][搜索][模拟][贪心]

来源:互联网 发布:深圳龙岗ug编程培训 编辑:程序博客网 时间:2024/05/21 00:49

又回到最初的起点……
而我仍是如此蒟蒻。
噗那就一步一步慢慢来吧不着急2333。
T1:模拟题,小心一个是不要枚举成1到n了,一个是写存在继续操作写习惯了,忘了打非符号。
记得昨年考的时候有个等号少写了检查了很久哈哈哈。

#include<iostream>#include<cstdio>using namespace std;int n,ans[50][50];int main(){    freopen("magic.in","r",stdin);    freopen("magic.out","w",stdout);    scanf("%d",&n);    ans[1][(n+1)/2]=1;    for(int i=2;i<=n*n;i++)    for(int j=1;j<=n;j++)    for(int k=1;k<=n;k++)    if(ans[j][k]==i-1){    if(j==1&&k==n){    ans[j+1][k]=i;    }    else if(j==1){        ans[n][k+1]=i;    }    else if(k==n){    ans[j-1][1]=i;    }    else{    if(!ans[j-1][k+1])ans[j-1][k+1]=i;    else ans[j+1][k]=i;    }    }    for(int i=1;i<=n;i++){        for(int j=1;j<=n;j++)printf("%d ",ans[i][j]);        printf("\n");    }    return 0;}

T2:
题意:每次从每点同时向其父节点自己已有传输信息(每点有且仅有一父节点),求多久后传到自己这里。
分析:记得当时拿的模拟分hhh.
分析一下就知道拿到自己的要在环上,所以要求最小环。
然而n三方,所以继续找没用到的特点,嗯n点n边,只要找到强连通分量就不可能一个套另一个强连通分量(不然边不够)
所以写了个诡异的dfs,思路还是tarjan.

#include<iostream>#include<cstdio>using namespace std;const int maxn=2e5+5;int mini=2e9,n,tov[maxn],dep[maxn],used[maxn];int dfs(int u,int ste){    dep[u]=ste;    if(!used[tov[u]]) {    if(dep[tov[u]]){    used[u]=1;    return dep[u]-dep[tov[u]]+1;    }    int ans=dfs(tov[u],ste+1);    used[u]=1;    return ans;    }    used[u]=1;    return (int)2e9;}int main(){    freopen("message.in","r",stdin);    freopen("message.out","w",stdout);    scanf("%d",&n);    for(int i=1;i<=n;i++)scanf("%d",&tov[i]);    for(int i=1;i<=n;i++)if(!used[i])        mini=min(mini,dfs(i,1));    printf("%d",mini);    return 0;}

T3:做到这里还有两个小时(一共考3h),但我,没有胆量花时间去分析,上手就暴力,最后发现好像大家分都高得吓人,这里要反思、要静下心来分析,平时考试分数不是最重要的,而且也看得出来这是简单题,划线又不按照分数划。
题意:给定一副牌,有不同的走牌方式,求怎样最快走完。
分析:(我觉得它的思路是把不能贪心的地方先枚举,剩下的贪心,不过出题人想的应该是map记忆化搜索不然不会给这么大内存。
然后就是直接分析贪心会发现不能贪心,仔细观察发现基本上问题都出现在顺子上,先把顺子给枚举了,剩下的地方就可以贪心了。
这种方法没用过,挺巧妙的。)
5min后补充:上述方法实力打脸,随机数据给了贪心太多施展自己力量的空间然后这个贪心是错的。
包括day1AK了的两位大神,跑出来的答案,都是错的。
幸好我记得去证明QAQ
下面的程序是错的QAQ

#include<iostream>#include<cstdio>#include<cstring>#define clr(x) memset(x,0,sizeof(x))using namespace std;int n,t,cur[30],num,col,mini,tot[5];int calc(){    clr(tot);int ret=0;    for(int i=0;i<=14;i++)tot[cur[i]]++;    while(tot[4]&&tot[2]>=2){        ret++;tot[4]--;tot[2]-=2;    }    while(tot[4]&&tot[1]>=2){        ret++;tot[4]--;tot[1]-=2;    }    while(tot[3]&&tot[2]){        ret++;tot[3]--;tot[2]--;    }    while(tot[3]&&tot[1]){        ret++;tot[3]--;tot[1]--;    }    if(cur[1]&&cur[0]&&tot[1]>=2)tot[1]--;    return ret+tot[4]+tot[3]+tot[2]+tot[1];}void dfs(int ste){    if(ste>mini)return;    mini=min(mini,ste+calc());    for(int i=3;i<=13;i++)if(cur[i]>=3){        cur[i]-=3;int j=i+1;       for(j=i+1;j<=14;j++)if(cur[j]<3)break;       else {           cur[j]-=3;           dfs(ste+1);       }       for(int k=i;k<j;k++)cur[k]+=3;    }    for(int i=3;i<=12;i++)if(cur[i]>=2){        cur[i]-=2;int j=i+1;       for(j=i+1;j<=14;j++)if(cur[j]<2)break;       else {           cur[j]-=2;           if(j-i>=2)dfs(ste+1);       }       for(int k=i;k<j;k++)cur[k]+=2;    }    for(int i=3;i<=10;i++)if(cur[i]){        cur[i]--;int j=i+1;       for(j=i+1;j<=14;j++)if(!cur[j])break;       else {           cur[j]--;           if(j-i>=4)dfs(ste+1);       }       for(int k=i;k<j;k++)cur[k]++;    }}int main(){    freopen("landlords.in","r",stdin);    freopen("landlords.out","w",stdout);    scanf("%d %d",&t,&n);    for(int i=1;i<=t;i++){        clr(cur);mini=2e9;        for(int i=1;i<=n;i++){            scanf("%d %d",&num,&col);            if(num>=2)cur[num]++;            else if(num==1)cur[14]++;            else if(col==1)cur[0]++;            else cur[1]++;        }        dfs(0);        printf("%d\n",mini);    }    return 0;}

我马上写个正确的,我错了QWQ

#include<iostream>#include<cstdio>#include<cstring>#define clr(x) memset(x,0,sizeof(x))using namespace std;int n,t,cur[30],num,col,mini;int calc(){    int ret=0;    for(int i=0;i<=14;i++)if(cur[i])ret++;    if(cur[0]&&cur[1])ret--;    return ret;}void dfs(int ste){    if(ste>mini)return;    mini=min(mini,ste+calc());    for(int i=3;i<=13;i++)if(cur[i]>=3){        cur[i]-=3;int j=i+1;       for(j=i+1;j<=14;j++)if(cur[j]<3)break;       else {           cur[j]-=3;           dfs(ste+1);       }       for(int k=i;k<j;k++)cur[k]+=3;    }    for(int i=3;i<=12;i++)if(cur[i]>=2){        cur[i]-=2;int j=i+1;       for(j=i+1;j<=14;j++)if(cur[j]<2)break;       else {           cur[j]-=2;           if(j-i>=2)dfs(ste+1);       }       for(int k=i;k<j;k++)cur[k]+=2;    }    for(int i=3;i<=10;i++)if(cur[i]){        cur[i]--;int j=i+1;       for(j=i+1;j<=14;j++)if(!cur[j])break;       else {           cur[j]--;           if(j-i>=4)dfs(ste+1);       }       for(int k=i;k<j;k++)cur[k]++;    }       for(int i=2;i<=14;i++)if(cur[i]>=4){        cur[i]-=4;        for(int j=2;j<=14;j++)if(cur[j]>=2){        cur[j]-=2;        for(int k=2;k<=14;k++)if(cur[k]>=2){            cur[k]-=2;            dfs(ste+1);            cur[k]+=2;        }        cur[j]+=2;        }        cur[i]+=4;    }    for(int i=2;i<=14;i++)if(cur[i]>=4){        cur[i]-=4;        for(int j=0;j<=14;j++)if(cur[j]){        cur[j]--;        for(int k=0;k<=14;k++)if(cur[k]){            cur[k]--;            dfs(ste+1);            cur[k]++;        }        cur[j]++;        }        cur[i]+=4;    }    for(int i=2;i<=14;i++)if(cur[i]>=3){        cur[i]-=3;        for(int j=2;j<=14;j++)if(cur[j]>=2){        cur[j]-=2;        dfs(ste+1);        cur[j]+=2;        }        cur[i]+=3;    }    for(int i=2;i<=14;i++)if(cur[i]>=3){        cur[i]-=3;        for(int j=0;j<=14;j++)if(cur[j]){        cur[j]--;        dfs(ste+1);        cur[j]++;        }        cur[i]+=3;    }}int main(){    freopen("landlords.in","r",stdin);    freopen("landlords.out","w",stdout);    scanf("%d %d",&t,&n);    for(int i=1;i<=t;i++){        clr(cur);mini=2e9;        for(int i=1;i<=n;i++){            scanf("%d %d",&num,&col);            if(num>=2)cur[num]++;            else if(num==1)cur[14]++;            else if(col==1)cur[0]++;            else cur[1]++;        }        dfs(0);        printf("%d\n",mini);    }    return 0;}

这个是对的……然后这是YJQ大神的剪枝,其实就是贪心,因为能带就带上肯定不会出问题!而且没带的也都枚举了,其实只是省去了由于排序出现的重复计算以及很多不必要的计算(比如上界的计算,就不用去跑了,直接递推);(顺序问题的精简很重要!)
CSZ做的是DP,存了四维,然后针对不同情况来计算,只需要搜顺子就可以了(因为只在顺子里数码会有影响),我觉得这个就是我上面被打脸了的那个“排除不能被贪心的因素”对应的“排除一些元素让DP好表示”;

0 0
原创粉丝点击