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

8 篇文章 0 订阅
5 篇文章 0 订阅

又回到最初的起点……
而我仍是如此蒟蒻。
噗那就一步一步慢慢来吧不着急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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值