AOJ 2126 Alien Pianist

21 篇文章 0 订阅

题意繁琐, 不想写了......还是自己看题去吧...

最后我是简化为求一个DAG图的最长路径, 用dfs+剪枝+记忆化搜索dp来完成

本题一共有223个测试数据, 本来第222个test本地运行之后崩掉了...dfs的太深, 栈溢出了orz, 可是提交上oj之后却是AC. 果然LINUX博大精深我不懂啊233

有需要第222个test的或者是要所有数据的可以私信...

学长建议我用bfs+topo序做, 下次试试吧...一开始写了个bfs的也是本地崩了然后重写了dfs... 不知道之前的那个程序能不能过呢

这题光是读题就花了很久, 没有题解而且卡题的时候感觉整个人都不好了orz, 特别想砸电脑....不过这也是一种锻炼吧, 毕竟只是08年日本队伍冬合宿的某一天的题而已, 一想到他们每天都要做6题这个难度的我就觉得自己弱爆了....

看到四五年前的几个老怪物写的似乎都比我短而且内存占用少... 不过效率上的话这个还是最快的^_^

就内存问题而言, 第一次AC我烧了51+兆内存...在next数组那里我开了100...事实上如果用正确的建图方法, 只要开3就行了

这样内存占用一口气降到了8M, 必须吸取教训→_→


/*author: birdstorm*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <climits>

#define MAXN 1005
#define N 105
#define inf 1.0e20
#define eps 1.0e-10
#define MOD 1000000007

#define For(i,m,n) for(int i=(m);i<(n);i++)
#define vecfor(iter,a) for(vector<int>::iterator iter=a.begin();iter!=a.end();iter++)
#define rep(i,m,n) for(int i=(m);i<=(n);i++)
#define repd(i,m,n) for(int i=(m);i>=(n);i--)
#define LL long long
#define test

using namespace std;
int cs=0, n, m, k, a[N], prevnum, tot;
int cnt[MAXN], start[MAXN], dp[MAXN*N];
bool isok;
struct node{
    int cntnext;
    int hasprev;
    int index;
    int next[3];
};
node scale[N*MAXN];
int d(int i)
{
    int &ans = dp[i];
    if(ans > 0) return ans;
    if(isok==false) return 0;
    ans = 1;
    for(int j = 0;j < scale[i].cntnext;j++){
        ans=max(ans,d(scale[i].next[j])+1);
        if(ans>n){
            isok=false;
            return 0;
        }
    }
    return ans;
}
int main()
{
    #ifndef test
        //freopen("pianist_input.txt","r",stdin);
        //freopen("AC_test.txt","r",stdin);
        freopen("pianist.in","r",stdin);
        freopen("pianist_output.txt","w",stdout);
    #endif // test
    while(scanf("%d%d",&n,&m),n||m){
        tot=0; cs++;
        int Max=0;
        isok=true;
        start[0]=0;
        For(i,0,m){
            scanf("%d",&cnt[i]);
            int head=0;
            bool c=true;
            if(i) start[i]=start[i-1]+cnt[i-1];
            For(j,0,cnt[i]) scanf("%d",&a[j]);
            sort(a,a+cnt[i]);
            For(j,0,cnt[i]){
                scale[tot].index=a[j];
                scale[tot].cntnext=0;
                if(j) scale[tot].hasprev=1;
                else scale[tot].hasprev=0;
                if(j!=cnt[i]-1) scale[tot].next[scale[tot].cntnext++]=tot+1;
                dp[tot]=-1;
                tot++;
            }
            if(i){
                int head1=0, head2=0;
                while(head1<cnt[i-1]&&head2<cnt[i]){
                    int t1=start[i-1]+head1, t2=start[i]+head2;
                    int pt1=t1, pt2=t2;
                    while(scale[t1].index<scale[t2].index&&head1<cnt[i-1])  t1++,head1++;
                    if(t1!=pt1) scale[t1-1].next[scale[t1-1].cntnext++]=t2;
                    while(scale[t2].index<scale[t1].index&&head2<cnt[i])  t2++,head2++;
                    if(t2!=pt2) scale[t2-1].next[scale[t2-1].cntnext++]=t1;
                }
            }
        }
        //For(i,0,tot) {printf("%d: ",i); For(j,0,scale[i].cntnext) printf("%d ",scale[i].next[j]); puts("");}
        For(i,0,m){
            int t=start[i];
            if(scale[t].hasprev==0) dp[t]=d(t), Max=max(Max,dp[t]);
            if(isok==false) break;
        }
        if(Max>n||!isok) printf("Case %d: No\n",cs);
        else printf("Case %d: Yes\n",cs);
    }
    return 0;
}

/*
6 2
3 2 4 7
3 3 6 8
5 2
3 2 4 7
3 3 6 8
8 8
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7
7 8
1 0
1 1
1 2
1 3
1 4
1 5
1 6
1 7
13 10
1 512634628
6 1652933534 213546428 677347949 658345883 956908147 1031367795
3 2037809726 116667955 790987801
2 760105898 1094137029
5 1101583585 573358560 1598796630 561655915 1837702701
4 631617329 1253820193 488205827 186025101
2 458983056 969671259
3 1421327126 1482305888 228207250
4 1695852316 905555199 1585122896 505276815
5 1339721960 395602894 2053590949 2130709761 995386565
12 10
1 512634628
6 1652933534 213546428 677347949 658345883 956908147 1031367795
3 2037809726 116667955 790987801
2 760105898 1094137029
5 1101583585 573358560 1598796630 561655915 1837702701
4 631617329 1253820193 488205827 186025101
2 458983056 969671259
3 1421327126 1482305888 228207250
4 1695852316 905555199 1585122896 505276815
5 1339721960 395602894 2053590949 2130709761 995386565
0 0
*/


代码附上的是前6组数据, 基本过了这6组可以表明程序大致没错了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值