人間夜行

一切の有為の法 夢幻泡影の如し

USACO训练测评初体验

| 评论

USACO确实是一个不错的OJ,它提供了一张TODO表指引学习。但由于是初体验,走了不少弯路。比如出现这样的错误:

> Run 1: Execution error: Your program had this runtime error:
Illegal file open (/dev/tty). The program ran for 0.000 CPU seconds before the error. It used 1808 KB of memory.
解决方法是把数组开大一点。(囧)

还有:

Note that your output did not end in a newline! This is an error and must be repaired.
这种情况也比较容易出现。输出加上一个换行吧。

USACO的测评有点奇葩,提交时还需要“Header comments”,不过习惯了就好了。

RQNOJ 162 奖金

| 评论

//这是一道完全背包。与0/1背包不同,空间优化后不必逆序,
//以实现多次选取。
//此外本题要求装满,所以f[j](j!=0)初始化为负无限大。
//关于“装满”,参见jake1036的《01背包问题总结(一)》。
#include <stdio.h>
#include <limits.h>
int main()
{
	long int n,m,p[10001],v[10002],f[10001];
	scanf("%ld%ld",&n,&m);
	int i,j;
	for(i=1;i<=n;i++) scanf("%ld%ld",&p[i],&v[i]);
	for(j=1;j<=m;j++) f[j]=LONG_MIN;
	for(i=1;i<=n;i++)
		for(j=p[i];j<=m;j++)
			if(f[j-p[i]]+v[i]>f[j]) f[j]=f[j-p[i]]+v[i];
	printf("%ld",f[m]);
	return 0;
}

苦逼的NOIP复赛

| 评论

事先声明,鄙人OI水平确实不高。各位切勿吐槽。

我是浙江的高一,初赛68.5分(?),用的是C,本来是刚好被分数线掐死,进不了复赛的。后来使用了杭州一个推荐名额(分数线以下可以多6人),进了。我记得这是我第一次进复赛,总共参赛两次。上次是初二,37分。初三那么空居然没被学校通知到参加培训。大大的遗憾。

停课一周集训之后,就去了余姚。话说我一开始还拿不出报名费,问老师借了几百块,直到今天才还上。还的时候老师居然对我说谢谢,我顿时无语了。周五下午,急急忙忙上完那一周去上的唯一一节课后(去政治演讲,仅五分钟,貌似讲得不错),坐宁波的校车走了。到了余姚,6点左右,直奔余姚中学。实际上报到时间已经过了,我们万能的拥有瞬移技能的老师给组委会那边打了个电话以后,最终被允许迟到几分钟。领了证件,领了饭票(周五晚,六、日午),去吃饭。余姚中学的饭确实好吃,比余姚实验学校的好吃多了。可惜我是应去余姚实验学校比赛,这饭是没的吃了。吃完,便去银河宾馆。躺在床上看《骗分导论》。《骗分导论》是个好东西,具体不解释,嘿嘿。后悔没带电脑去,空闲时间真无聊。有人带了,玩了两天。

RQNOJ 589 N皇后加强版

| 评论

//递归法。所幸规模小。
#include <stdio.h>
int n;
int sum=0;
int lie[14]={0};
int zh[14]={0};
int zzx[30]={0};
int zfx[30]={0};
void try(int i)
{
        if(i>n)
        {
                if(sum<3)
                {
                        int s;
                        for(s=1;s<n;s++) printf("%d ",lie[s]);
                        printf("%d\n",lie[s]);
                }
                sum++;
        }
        else
        {
                int r;
                for(r=1;r<=n;r++)
                        if(zh[r]==0&&zzx[i+r]==0&&zfx[i-r+n]==0)
                        {
                                lie[i]=r;
                                zh[r]=1;
                                zzx[i+r]=1;
                                zfx[i-r+n]=1;
                                try(i+1);
                                zh[r]=0;
                                zzx[i+r]=0;
                                zfx[i-r+n]=0;
                        }
        }
}

int main()
{         scanf("%d",&n);
        try(1);
        printf("%d",sum);
        return 0;
}

RQNOJ 62 [NOIP2002]均分纸牌

| 评论

//其实就是最笨的办法。想太多就死了。
#include <stdio.h>
int main()
{
        int n;
        int f[101];
        scanf("%d",&n);
        int i,sum=0;
        for(i=1;i<=n;i++)
        {
                scanf("%d",&f[i]);
                sum+=f[i];
        }
        sum/=n;
        int count=0;
        for(i=1;i<n;i++)
        {
                if(f[i]!=sum)
                {
                        f[i+1]+=f[i]-sum;
                        f[i]=sum;
                        count++;
                }
        }
        printf("%d",count);
        return 0;
}

RQNOJ 5 采药

| 评论

//本次将讨论0/1背包的空间优化问题。
//这是未优化的。显然数组开不大。
#include <stdio.h>
int max(int a,int b)
{
    if(a>b) return a;
    else return b;
}
int main()
{
    int t,m;
    int v[101],c[101],f[101][1001];
    int i,r;
    scanf("%d%d",&t,&m);
    for(i=1;i<=m;i++) scanf("%d%d",&c[i],&v[i]);
    for(r=0;r<=t;r++) if(r<c[1]) f[1][r]=0; else f[1][r]=v[1];
    for(i=2;i<=m;i++)
        for(r=0;r<=t;r++) 
            if(r>=c[i])
                f[i][r]=max(f[i-1][r],f[i-1][r-c[i]]+v[i]);
            else
                f[i][r]=f[i-1][r];
    printf("%d",f[m][t]);
    return 0;
}
/*------------------------华丽丽----------------------------*/
//优化过的。
//事实上f[i][r]一开始用的还是f[i-1][r]的值,因此实际上只需要一个数组。
#include <stdio.h>
int max(int a,int b)
{
	if(a>b) return a;
	else return b;
}
int main()
{
	int t,m;
	int v[101],c[101],f[1001];
	int i,r;
	scanf("%d%d",&t,&m);
	for(i=1;i<=m;i++) scanf("%d%d",&c[i],&v[i]);
	for(r=0;r<=t;r++) if(r<c[1]) f[r]=0; else f[r]=v[1];
	for(i=2;i<=m;i++)
//关键!为保证本次所需要的未用数据不改变,令r递减。
		for(r=t;r>=0;r--) 
			if(r>=c[i])
				f[r]=max(f[r],f[r-c[i]]+v[i]);
			else
				f[r]=f[r];
	printf("%d",f[t]);
	return 0;
}

RQNOJ 486 排座椅

| 评论

//统计每一排的对数,即拆散后可得对数。然后从大的开始取。(贪心一道)
//注意输出排数时要从小到大。
//同时注意输出时的格式。换行、空格之类的。
#include <stdio.h>
int map[2001][5];
int hang[1001]={0};
int lie[1001]={0};
int m,n,k,l,d;
int cmp(const void *a,const void *b)
{
        return *(int *)a-*(int *)b;
}
int maxhpos()
{
        int i;
        int max=0;
        int maxpos=0;
        for(i=1;i<=m;i++)
                if(hang[i]>max)
                {
                        max=hang[i];
                        maxpos=i;
                }
        hang[maxpos]=0;
        return maxpos;
}
int maxlpos()
{
        int i;
        int max=0;
        int maxpos=0;
        for(i=1;i<=n;i++)
                if(lie[i]>max)
                {
                        max=lie[i];
                        maxpos=i;
                }
        lie[maxpos]=0;
        return maxpos;
}
int min(int a,int b)
{
        if(a<b) return a;
        else return b;
}
int main()
{
        scanf("%d%d%d%d%d",&m,&n,&k,&l,&d);
        int i,r;
        int chu1[1001],chu2[1001];
        for(i=1;i<=d;i++)
        {
                scanf("%d%d%d%d",&map[i][1],&map[i][2],&map[i][3],&map[i][4]);
                if(map[i][1]==map[i][3]) lie[min(map[i][2],map[i][4])]++;
                if(map[i][2]==map[i][4]) hang[min(map[i][1],map[i][3])]++;
        }
        for(i=1;i<=k;i++)
        {
                chu1[i]=maxhpos();
        }
        for(i=1;i<=l;i++)
        {
                chu2[i]=maxlpos();
        }
        qsort(&chu1[1],k,sizeof(chu1[1]),cmp);
        qsort(&chu2[1],l,sizeof(chu2[1]),cmp);
        for(i=1;i<k;i++) printf("%d ",chu1[i]);printf("%d",chu1[i]);
        printf("\n");
        for(i=1;i<l;i++) printf("%d ",chu2[i]);printf("%d",chu2[i]);
        return 0;
}

RQNOJ 399 [NOIP2008]笨小猴

| 评论

//有时候多写几个函数有助于调试。
#include <stdio.h>
#include <string.h>
int stat[26];
char word[101];
int len;
void cls()
{
        int i;
        for(i=0;i<26;i++) stat[i]=0;
}
void tj()
{
        cls();
        int i;
        for(i=0;i<len;i++) stat[word[i]-'a']++;
}
int getmax()
{
        int max=0;
        int i;
        for(i=0;i<26;i++)
        {
                if(stat[i]>max)
                {
                        max=stat[i];
                }
        }
        return max;
}
int getmin()
{
        int min=100;
        int i;
        for(i=0;i<26;i++)
        {
                if(stat[i]<min&&stat[i]!=0)
                {
                        min=stat[i];
                }
        }
        return min;
}
int isprime(int num)
{
        int prime[25]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
        int i;
        for(i=0;i<25;i++) if(num==prime[i]) return 1;
        return 0;
}
int main()
{
        gets(word);
        len=strlen(word);
        int a;
        tj();
        a=getmax()-getmin();
        if(isprime(a))
        {
                printf("Lucky Word\n");
                printf("%d",a);
        }
        else
        {
                printf("No Answer\n");
                printf("0");
        }
        return 0;
}

RQNOJ 394 [NOIP2008]火柴棒等式

| 评论

//很忐忑地把1000以内的爆搜交上去了。结果万幸。
#include <stdio.h>
int stick[10]={6,2,5,5,4,5,6,3,7,6};
int tj(int num)
{
        if(num<10) return stick[num];
        else return stick[num%10]+tj(num/10);
}
int main()
{
        int i,r;
        int n;
        scanf("%d",&n);
        int count=0;
        for(i=0;i<=1000;i++)
                for(r=0;r<=1000;r++)
                        if(tj(i)+tj(r)+tj(i+r)==n-4) count++;
        printf("%d",count);
        return 0;
}

RQNOJ 114 大合数分解

| 评论

//怕数字开的不够大。也怕超时。两难啊。只好猜范围了。
#include <stdio.h>
int main()
{
        char list[100001]={0};
        unsigned long int i=2;
        unsigned long int r;
        unsigned long int n;
        scanf("%d",&n);
        // 0 is prime;
        while(i<=100000)
        {
                if(list[i]==0)
                {
                        for(r=2*i;r<=100000;r+=i)
                                list[r]=1;
                }
                i++;
        }
        for(i=2;i<=100000;i++)
        {
                if(list[i]==0)
                {
                        while(n%i==0)
                        {
                                printf("%d ",i);
                                n/=i;
                        }
                }
        }
        return 0;
}