Loading

NOIP2002提高組 均分紙牌

2011年10月09日 02:49

[问题描述]
有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若于张纸牌,然后移动。
移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。

例如 N=4,4 堆纸牌数分别为:
① 9 ② 8 ③ 17 ④ 6
移动3次可达到目的:
从 ③ 取 4 张牌放到 ④ (9 8 13 10) -> 从 ③ 取 3 张牌放到 ②(9 11 10 10)-> 从 ② 取 1 张牌放到①(10 10 10 10)。

[输 入]
N(N 堆纸牌,1 <= N <= 100)
A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000)

[输 出]
输出至屏幕。格式为:
所有堆均达到相等时的最少移动次数。‘

[输入输出样例]
4
9 8 17 6

[输入输出样例]
3

解析見http://www.byvoid.com/blog/noip-allsolutions/

 

#include <iostream>
#include <cstdio>
using namespace std;

int N,avg,ans;
int S[101];

int main()
{
    int i;
    freopen("jfzp.in","r",stdin);
    freopen("jfzp.out","w",stdout);
    cin >> N;
    for (i=1;i<=N;i++)
    {
        cin >> S[i];
        avg+=S[i];
    }
    avg/=N;
    for (i=1;i<N;i++)
    {
        if (S[i]!=avg)
        {
            S[i+1]+=S[i]-avg;
            S[i]=avg;
            ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}

正在连接评测机...

 

已连接到评测机

GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty

正在编译...

编译成功

 

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 20 0.030 s 273 KB 0
2 正确 20 0.002 s 273 KB 0
3 正确 20 0.011 s 273 KB 0
4 正确 20 0.001 s 273 KB 0
5 正确 20 0.001 s 273 KB 0

运行完成

运行时间 0.045 s

平均内存使用 273 KB

测试点通过状况 AAAAA

得分:100

恭喜你通过了全部测试点!

Tags: NOIP c++ 貪心
评论(1) 阅读(5141)

NOIP2000提高組 進制轉換

2011年10月09日 02:33

描述 Description

我们可以用这样的方式来表示一个十进制数:将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式。例如,123可表示为1*10^2+2*10^1+3*10^0这样的形式。
与之相似的,对二进制数来说,也可表示成每个二进制数码乘以一个以该数字所处位置的(值-1)为指数,以2为底数的幂之和的形式。一般说来,任何一个正整 数R或一个负整数-R都可以被选来作为一个数制系统的基数。如果是以R或-R为基数,则需要用到的数码为0,1,....R-1。例如,当R=7时,所需 用到的数码是0,1,2, 3,4,5和6,这与其是R或-R无关。如果作为基数的数绝对值超过10,则为了表示这些数码,通常使用英文字母来表示那些大于9的数码。例如对16进制 数来说,用A表示10,用B表示11,用C表示12,用D表示13,用E表示14,用F表示15。在负进制数中是用-R作为基数,例如-15(+进制)相 当于110001(-2进制),
并且它可以被表示为2的幂级数的和数:
110001=1*(-2)^5+1*(-2)^4+0*(-2)^3+0*(-2)^2+0*(-2)^1+1*(-2)^0
问题求解:
设计一个程序,读入一个十进制数的基数和一个负进制数的基数,并将此十进制数转换为此负进制下的数:-R∈{-2,-3,-4,....-20}

输入格式 Input Format

输入文件有若干行,每行有两个输入数据。
第一个是十进制数N(-32768<=N<=32767); 第二个是负进制数的基数-R。

输出格式 Output Format

输出此负进制数及其基数,若此基数超过10,则参照16进制的方式处理。【具体请参考样例】

样例输入 Sample Input

30000 -2
-20000 -7
28800 -16
-25000 -16

样例输出 Sample Output

30000=11011010101110000(base -2)
-20000=263526(base -7)
28800=19180(base -16)
-25000=7FB8(base -16)

 

【分析】

比較基礎的題,只要注意整除函數即可。

以下代碼是BYVoid(www.byvoid.com)大牛的:

#include <iostream>
#include <cstdio>
using namespace std;
int N,M,base;

inline int Div(int a,int b)
{
	int n;
	n=a/b;
	if (n*b<=a)
		return n;
	return n+1;
}

void work()
{
	int num[100];
	int top=0;
	if(N==0)
	{
		cout<<0;
	}
	int P;
	while (N)
	{
		P=Div(N,base);
		num[++top]=N-P*base;
		N=P;
	}
	for (;top>=1;top--)
	{
		if (num[top]<10)
			cout<<num[top];
		if (num[top]>=10)
			cout<<(char)(num[top]-10+'A');
	}
		cout<<"(base "<<base<<")"<<endl;
}

int main()
{
	freopen("fjz.in","r",stdin);
	freopen("fjz.out","w",stdout);
	while(cin>>N)
	{
		cin>>base;
		M=N;
		cout<<N<<"=";
		work();
	}
	return 0;
}

 

 

正在连接评测机...

 

已连接到评测机

GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty

正在编译...

编译成功

 

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 10 0.000 s 273 KB 0
2 正确 10 0.000 s 273 KB 0
3 正确 10 0.000 s 273 KB 0
4 正确 10 0.000 s 273 KB 0
5 正确 10 0.000 s 273 KB 0
6 正确 10 0.000 s 273 KB 0
7 正确 10 0.000 s 273 KB 0
8 正确 10 0.000 s 273 KB 0
9 正确 10 0.000 s 273 KB 0
10 正确 10 0.000 s 273 KB 0

运行完成

运行时间 0.003 s

平均内存使用 273 KB

测试点通过状况 AAAAAAAAAA

得分:100

恭喜你通过了全部测试点!

 

Tags: NOIP c++
评论(1) 阅读(2056)

NOIP2001提高組 一元三次方程求解

2011年10月08日 03:41

问题描述
有形如:ax3+bx2+cx+d=0  这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d  均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的绝对值>=1。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后2位。
提示:记方程f(x)=0,若存在2个数x1和x2,且x1<x2,f(x1)*f(x2)<0,则在(x1,x2)之间一定有一个 根。

样例
输入:1   -5   -4   20
输出:-2.00   2.00   5.00

【分析】

由於精度不大,直接枚舉即可。

一下代碼參考了BYVoid(http://www.byvoid.com)的代碼~他的代碼比我的簡練多了~

#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
	double a,b,c,d,x,v;
	int X;
	freopen("3cfc.in","r",stdin);
	freopen("3cfc.out","w",stdout);
	cin>>a>>b>>c>>d;
	for (X=-10000;X<=10000;x=(++X)/100.0)
	{
		v=a*x*x*x+b*x*x+c*x+d;
		if (v>=-0.01 && v<=0.01)	
			printf("%.2lf ",x);	
	}
	return 0;
}

正在连接评测机...

 

已连接到评测机

GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty

正在编译...

编译成功

 

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 20 0.027 s 273 KB 0
2 正确 20 0.001 s 273 KB 0
3 正确 20 0.001 s 273 KB 0
4 正确 20 0.001 s 273 KB 0
5 正确 20 0.001 s 273 KB 0

运行完成

运行时间 0.031 s

平均内存使用 273 KB

测试点通过状况 AAAAA

得分:100

恭喜你通过了全部测试点!

 

Tags: NOIP c++ 枚舉 模擬
评论(2) 阅读(3366)

NOIP2004提高組 合併果子

2011年10月08日 03:26

【问题描述】
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。
【输入文件】
输入文件fruit.in包括两行,第一行是一个整数n(1<=n<=10000),表示果子的种类数。第二行包含n个整数,用空格分隔,第i个整数ai(1<=ai<=20000)是第i种果子的数目。
【输出文件】
输出文件fruit.out包括一行,这一行只包含一个整数,也就是最小的体力耗费值。输入数据保证这个值小于231。
【样例输入】
3
1 2 9
【样例输出】
15
【数据规模】

对于30%的数据,保证有n<=1000:
对于50%的数据,保证有n<=5000;
对于全部的数据,保证有n<=10000。

【分析】

貪心,每次找到最小的兩堆果子進行合併。

不要把本題看成石子歸併。

我用的是鏈表,全過了,但是速度較慢~

#include <fstream>
using namespace std;	
ifstream fin("fruit.in");
ofstream fout("fruit.out");
class data
{
public:
	int key;
	//Other members HERE...
	int sen;//前驱
	int next;//后继
};
data A[200000];
int top;//链表中元素的个数

void Insert(int key)
{
	int point=0;
	while (key>A[point].key)
	{
		point=A[point].next;
	}
	//Create a new node
	A[top].key=key;
	A[top].next=point;
	A[top].sen=A[point].sen;
	
	A[point].sen=top;//后继的前驱等于自己
	
	A[A[top].sen].next=top;//前驱的后继等于自己
	
	top++;
}

void DeleteOne(int key)
{
	int point=A[0].next; 
	while(A[point].next!=-1)
	{
		if(A[point].key==key)
		{
			A[A[point].sen].next=A[point].next; //自己前驱的后继等于自己的后继
			A[A[point].next].sen=A[point].sen;  //自己后继的前驱等于自己的前驱
			return; //跳出函数
		}
		point=A[point].next;
	}
}

void print()
{
	int point=A[0].next; 
	while(A[point].next!=-1)
	{
		fout<<A[point].key<<endl;
		point=A[point].next;
	}
}
void debug()
{
	for (int i=0;i<top;i++)
		fout<<i<<" "<<A[i].key<<" "<<A[i].sen<<" "<<A[i].next<<endl;
}

int GetMinElem()
{
	int point=A[0].next;
	return A[point].key;
}

int main()
{

	//Initialize
	A[0].key=-1;A[0].next=1;A[0].sen=-1;
	A[1].key=0Xfffffff;A[1].next=-1;A[0].sen=0;
    top=2;
	int num,key;
	fin>>num;
	for (int i=0;i<num;i++)
	{
		fin>>key;
		Insert(key);//插入一个关键字
	}
	
	int liu=num;
	int cost=0;
	//debug();
	while (liu!=1)
	{
		int m=GetMinElem();
		DeleteOne(m);
		int n=GetMinElem();
		DeleteOne(n);
		//fout<<m<<" "<<n<<endl<<endl;
		cost+=(m+n);
		Insert(m+n);
		liu--;
	}
	//print();
	fout<<cost<<endl;
	return 0;
}

 

正在连接评测机...

 

已连接到评测机

GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty

正在编译...

编译成功

 

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 10 0.000 s 2614 KB 0
2 正确 10 0.002 s 2614 KB 0
3 正确 10 0.002 s 2614 KB 0
4 正确 10 0.043 s 2614 KB 0
5 正确 10 0.096 s 2614 KB 0
6 正确 10 0.403 s 2614 KB 0
7 正确 10 0.503 s 2614 KB 0
8 正确 10 0.396 s 2614 KB 0
9 正确 10 0.500 s 2614 KB 0
10 正确 10 0.508 s 2614 KB 0

运行完成

运行时间 2.453 s

平均内存使用 2614 KB

测试点通过状况 AAAAAAAAAA

得分:100

恭喜你通过了全部测试点!

 

Tags: noip 貪心 c++
评论(1) 阅读(1451)

NOIP2006普及組 明明的隨機數

2011年10月08日 03:10

【问题描述】
    明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 1 到 1000 之间的随机整数( N ≤ 100 ),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按 照 排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。

【输入格式】
     输入文件 random.in 有 2 行,第 1 行为 1 个正整数,表示所生成的随机数的个数:N

     第 2 行有 N 个用空格隔开的正整数,为所产生的随机数。

【输出格式】
     输出文件 random.out 也是 2 行,第 1 行为 1 个正整数 M ,表示不相同的随机数的个数。第 2 行为 M 个用空格隔开的正整数,为从小到大排好序的不相同的随机数。

【输入输出样例】
 
输入:
10
20 40 32 67 40 20 89 300 400 15
 

输出:
8
15 20 32 40 67 89 300 400

【分析】

水題,直接模擬。

//NOIP2006-Junior-Random
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;

int Compare(const void *a,const void *b)
{
	return *(int *)a-*(int *)b;
}

int main()
{
	freopen("random.in","r",stdin);
	freopen("random.out","w",stdout);
	int num[101]={0};
	int n;
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d",&num[i]);
	int reduce=0;
	for (int i=1;i<=n;i++)
		for (int j=i+1;j<=n;j++)
			if (num[j]!=1001 && num[i]!=1001 && num[j]==num[i])
				{
					num[j]=1001;
					reduce++;
				}
	qsort(num+1,n,sizeof(int),Compare);
	cout<<n-reduce<<endl;
	for(int i=1;i<=n-reduce;i++)
		cout<<num[i]<<" ";
	cout<<endl;
	return 0;
}

 

正在连接评测机...

 

已连接到评测机

GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty

正在编译...

编译成功

 

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 10 0.018 s 273 KB 0
2 正确 10 0.001 s 273 KB 0
3 正确 10 0.001 s 273 KB 0
4 正确 10 0.001 s 273 KB 0
5 正确 10 0.001 s 273 KB 0
6 正确 10 0.001 s 273 KB 0
7 正确 10 0.001 s 273 KB 0
8 正确 10 0.001 s 273 KB 0
9 正确 10 0.001 s 273 KB 0
10 正确 10 0.001 s 273 KB 0

运行完成

运行时间 0.024 s

平均内存使用 273 KB

测试点通过状况 AAAAAAAAAA

得分:100

恭喜你通过了全部测试点!

Tags: NOIP c++ 模擬
评论(1) 阅读(10409)

NOIP2006普及組 開心的金明

2011年10月08日 02:59

【问题描述】
     金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎 么布置,你说了算,只要不超过 N 元钱就行”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的 N 元。于是,他把每件物品规定了一个重要度,分为 5 等:用整数 1 ~ 5 表示,第 5 等最重要。他还从因特网上查到了每件物品的价格(都是整数元)。他希望在不超过 N 元(可以等于 N 元)的前提下,使每件物品的价格与重要度的乘积的总和最大。

设第 j 件物品的价格为 v[j] ,重要度为 w[j] ,共选中了 k 件物品,编号依次为 j1 , j2 ,……, jk ,则所求的总和为:

v[j1]*w[j1]+v[j2]*w[j2]+ … +v[jk]*w[jk] 。(其中 * 为乘号)

请你帮助金明设计一个满足要求的购物单。

【输入格式】
     输入文件 happy.in 的第 1 行,为两个正整数,用一个空格隔开:

N m

(其中 N ( < 30000 )表示总钱数, m ( <25 )为希望购买物品的个数。)

从第 2 行到第 m+1 行,第 j 行给出了编号为 j-1 的物品的基本数据,每行有 2 个非负整数

v p

(其中 v 表示该物品的价格 (v<=10000) , p 表示该物品的重要度 (1~5) )

【输出格式】
     输出文件 happy.out 只有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值( <100000000 )。

【输入输出样例】
 
输入:
1000 5
800 2
400 5
300 5
400 3
200 2
 

输出:
3900

#include <iostream>
#include <cstdio>
using namespace std;
int TolM;//總錢數
int TolThing;//總物品
int F[26][100001];
class THING
{
public: 
	int v;//價格
	int p;//重要度
}T[25];

int getval(int i)
{
	return (T[i].v*T[i].p);
}

void init()
{
	cin>>TolM>>TolThing;
	for (int i=1;i<=TolThing;i++)
	{
		cin>>T[i].v>>T[i].p;
	}
	fclose(stdin);
	return;
}

void predp()
{
	int i,j;
	for (i=1;i<=TolThing;i++)
		for (j=1;j<=TolM;j++)
			F[i][j]=0;
	
	int q=getval(1);
	for (i=T[1].v;i<=TolM;i++)
	{
		F[1][i]=q;
	}
	return;
}

void print()
{
	int i,j;
	for (i=1;i<=TolThing;i++)
	{
		for (j=1;j<=TolM;j++)
			cout<<F[i][j]<<" ";
		cout<<endl;	
	}
	cout<<endl;
}

void dp()
{
	int i,j;
	for (i=2;i<=TolThing;i++)
	{
		for (j=1;j<=TolM;j++)
		{
			if (T[i].v>j)
				F[i][j]=F[i-1][j];
			else 
				F[i][j]=
				((F[i-1][j])>(F[i-1][j-T[i].v]+getval(i))?
				(F[i-1][j]):(F[i-1][j-T[i].v]+getval(i)));
		}
	}
}

int main()
{
	freopen("happy.in","r",stdin);
	freopen("happy.out","w",stdout);
	init();
	predp();
	dp();
	//print();
	cout<<F[TolThing][TolM]<<endl;
	return 0;
}

 

正在连接评测机...

 

已连接到评测机

GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty

正在编译...

编译成功

 

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 10 0.062 s 10428 KB 0
2 正确 10 0.001 s 10428 KB 0
3 正确 10 0.001 s 10428 KB 0
4 正确 10 0.001 s 10428 KB 0
5 正确 10 0.004 s 10428 KB 0
6 正确 10 0.003 s 10428 KB 0
7 正确 10 0.004 s 10428 KB 0
8 正确 10 0.005 s 10428 KB 0
9 正确 10 0.007 s 10428 KB 0
10 正确 10 0.001 s 10428 KB 0

运行完成

运行时间 0.089 s

平均内存使用 10428 KB

测试点通过状况 AAAAAAAAAA

得分:100

恭喜你通过了全部测试点!

Tags: NOIP c++ 動態規劃
评论(0) 阅读(1574)

NOIP2002普及組 選數

2011年10月08日 02:49

[问题描述]:


已知 n 个整数 x1,x2,…,xn,以及一个整数 k(k<n)。从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22  3+7+19=29  7+12+19=38  3+12+19=34。
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29)。
[输入]:
键盘输入,格式为:
n , k (1<=n<=20,k<n)
x1,x2,…,xn (1<=xi<=5000000)

[输出]:
格式为:一个整数(满足条件的种数)。
 
[输入输出样例]:
输入:choose.in
4 3
3 7 12 19
输出:choose.out
1

【分析】
排列組合問題,直接深度優先搜索(遞歸)即可。

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int sum=0;//當前總和
int num[21];
int n,k;
int tot=0;

bool prime(int num)
{
	if (num==1)return false;
	for (int i=2;i<=(int)sqrt(double(num));i++)
		if (num%i==0)
			return false;
	return true;	
}


void dg(int dep,int loc)
{
	if(k-dep>n-loc) return;
	if (dep==k+1)
	{
		if (prime(sum))
			tot++;
	}
	if (dep<k+1)
	{
		for (int i=loc;i<=n;i++)
		{
			sum+=num[i];
			dg(dep+1,i+1);
			sum-=num[i];
		}
	}
}

int main()
{
	freopen("choose.in","r",stdin);
	freopen("choose.out","w",stdout);
	cin>>n>>k;
	for (int i=1;i<=n;i++)
		cin>>num[i];
	dg(1,1);
	cout<<tot<<endl;
	return 0;
}

正在连接评测机...

 

已连接到评测机

GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty

正在编译...

编译成功

 

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 20 0.026 s 275 KB 0
2 正确 20 0.001 s 275 KB 0
3 正确 20 0.001 s 275 KB 0
4 正确 20 0.001 s 275 KB 0
5 正确 20 0.001 s 275 KB 0

运行完成

运行时间 0.028 s

平均内存使用 275 KB

测试点通过状况 AAAAA

得分:100

恭喜你通过了全部测试点!


Tags: c++ NOIP 深度優先搜索
评论(0) 阅读(1374)

NOIP2005 普及组 采药

2011年10月08日 02:26

【问题描述】

    辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难 题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段 时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”

如果你是辰辰,你能完成这个任务吗?

【输入文件】

   输入文件的第一行有两个整数 T ( 1 <= T <= 1000 )和 M ( 1 <= M <= 100 ),用一个空格隔开, T 代表总共能够用来采药的时间, M 代表山洞里的草药的数目。接下来的 M 行每行包括两个在 1 到 100 之间(包括 1 和 100 )的整数,分别表示采摘某株草药的时间和这株草药的价值。

【输出文件】

输出文件包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。

【样例输入】

70 3
71 100
69 1
1 2

【样例输出】

3

【数据规模】

对于 30% 的数据, M <= 10 ;

对于全部的数据, M <= 100 。

 

【分析】

本题是经典的0/1背包问题,直接DP即可。

 

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef unsigned short int usint;

class medic
{
public:
	usint t; //Time
	usint v; //Value
}Med[101];
usint T,M;//T: Total Time , M: The number of the medicine.
usint F[101][1001];

void init()
{
	cin>>T>>M;
	//初始化二維表
	for (usint i=1;i<=M;i++)
		for (usint j=1;j<=T;j++)
			F[i][j]=0;
	//從文件中讀入	
	for(usint i=1;i<=M;i++)
		cin>>Med[i].t>>Med[i].v;
	//預處理動態規劃 Pre-Dynamic Programing
	for (usint i=Med[1].t;i<=T;i++)
		F[1][i]=Med[1].v;
	return;
}

void Dynamic()
{
	usint i,j;
	for (i=2;i<=M;i++)
	{
		for(j=1;j<=T;j++)
		{
			if(Med[i].t>j)
				F[i][j]=F[i-1][j];
			else
			{
				F[i][j]=( (F[i-1][j]) > (F[i-1][j-Med[i].t]+Med[i].v) ?
					  (F[i-1][j]) : (F[i-1][j-Med[i].t]+Med[i].v) );
			}
		}
	}
}

int main()
{
	freopen("medic.in","r",stdin);
	freopen("medic.out","w",stdout);
	init();
	Dynamic();
	cout<<F[M][T]<<endl;
	return 0;
}

正在连接评测机...

 

已连接到评测机

GRID 1
名称 Flitty
系统版本 1.00
备注 COGS 1号评测机 Flitty

正在编译...

编译成功

 

测试点 结果 得分 运行时间 内存使用 退出代码
1 正确 10 0.024 s 464 KB 0
2 正确 10 0.001 s 464 KB 0
3 正确 10 0.002 s 464 KB 0
4 正确 10 0.002 s 464 KB 0
5 正确 10 0.002 s 464 KB 0
6 正确 10 0.002 s 464 KB 0
7 正确 10 0.002 s 464 KB 0
8 正确 10 0.002 s 464 KB 0
9 正确 10 0.002 s 464 KB 0
10 正确 10 0.001 s 464 KB 0

运行完成

运行时间 0.041 s

平均内存使用 464 KB

测试点通过状况 AAAAAAAAAA

得分:100

恭喜你通过了全部测试点!

Tags: c++ NOIP 動態規劃
评论(0) 阅读(2313)

USACO 1.2.2 Transformations題解

2011年9月21日 03:08

USACO 1.2.2 Transformations - Freddy - Freddy の ブログ

Transformations

A square pattern of size N x N (1 <= N <= 10) black and white square tiles is transformed into another square pattern. Write a program that will recognize the minimum transformation that has been applied to the original pattern given the following list of possible transformations:

  • #1: 90 Degree Rotation: The pattern was rotated clockwise 90 degrees.
  • #2: 180 Degree Rotation: The pattern was rotated clockwise 180 degrees.
  • #3: 270 Degree Rotation: The pattern was rotated clockwise 270 degrees.
  • #4: Reflection: The pattern was reflected horizontally (turned into a mirror image of itself by reflecting around a vertical line in the middle of the image).
  • #5: Combination: The pattern was reflected horizontally and then subjected to one of the rotations (#1-#3).
  • #6: No Change: The original pattern was not changed.
  • #7: Invalid Transformation: The new pattern was not obtained by any of the above methods.

In the case that more than one transform could have been used, choose the one with the minimum number above.

PROGRAM NAME: transform

INPUT FORMAT

Line 1: A single integer, N
Line 2..N+1: N lines of N characters (each either `@' or `-'); this is the square before transformation
Line N+2..2*N+1: N lines of N characters (each either `@' or `-'); this is the square after transformation

SAMPLE INPUT (file transform.in)

3 @-@ --- @@- @-@ @-- --@ 

OUTPUT FORMAT

A single line containing the the number from 1 through 7 (described above) that categorizes the transformation required to change from the `before' representation to the `after' representation.

SAMPLE OUTPUT (file transform.out)

1 

【分析】
     這道題其實就是對數組的變換,雖說有7種變換方式,其實只有兩種,一個是順時針旋轉90度,另一個是左右對稱,
其他的都可以由這兩個變換出來。

一開始先寫出三個函數,一個是把數組順時針旋轉90度的函數(在下面成為trans函數),另一個是左右對稱的函數(在
下面稱為fanshe函數),最後一個是判斷當前狀態與目標狀態是否相等的函數(check)。

【變換方式】
第一種 旋轉90度:調用一次trans(),然後check();
第二種 旋轉180度:兩次調用trans(),然後check();
第三種 旋轉270度:三次調用trans(),然後check();
第四種 反射:直接調用fanshe(),然後check();
第五種 組合: 1)先調用fanshe(),然後執行第一種變換方式,然後check();
                        2)先調用fanshe(),然後執行第二種變換方式,然後check();
                        3)先調用fanshe(),然後執行第三種變換方式,然後check();
第六種 無變化:直接調用check()
第七種 無法變換:最後在都無法變換的情況下,輸出7即可。


按照慣例,貼上我的複雜、冗長的代碼:
/*
ID:zyfwork1
PROB:transform
LANG:C++
*/
#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstring>
using namespace std;
ifstream fin("transform.in");
ofstream fout("transform.out");
char tran[12][12];
char res[12][12];
char temp[12][12];
char now[12][12];
int l; //正方形的邊長

void init();
void print();
void trans();

void init()
{
	fin>>l;
	register unsigned short int i,j;
	for (i=1;i<=l;i++)
		for (j=1;j<=l;j++)
			fin>>tran[i][j];
		
	for (i=1;i<=l;i++)
		for (j=1;j<=l;j++)
			fin>>res[i][j];
	return;
}

void print(int num)
{
	for (int i=1;i<=l;i++)
	{
		for (int j=1;j<=l;j++)
		{
			if (num==1) fout<<tran[i][j];
			if (num==2) fout<<temp[i][j];
			if (num==3) fout<<res[i][j];
			if (num==4) fout<<now[i][j];
		}
		fout<<endl;
	}
}

void trans()
{
	register unsigned short int i,j;
	for (i=1;i<=l;i++)
	{
		int t=1;
		for (j=l;j>=1;j--)
		{
			temp[i][t]=now[j][i];
			t++;
		}
	}
	for (i=1;i<=l;i++)
		for (j=1;j<=l;j++)
			now[i][j]=temp[i][j];
}

void initnow()
{
	register unsigned short int i,j;
	for (i=1;i<=l;i++)
		for (j=1;j<=l;j++)
			now[i][j]=tran[i][j];
}

void circle(int num)
{
	for (int i=1;i<=num;i++)
		trans();
}


bool check()
{
	register unsigned short int i,j;
	for (i=1;i<=l;i++)
	{
		for (j=1;j<=l;j++)
		{
			if(now[i][j]!=res[i][j]) return false;
		}
	}
	return true;
}

void fanshe()
{
	register unsigned short int i,j;
	for (i=1;i<=l;i++)
	{
		for (j=1;j<=l;j++)
		{
			now[i][j]=tran[i][l-j+1];
		}
	}
}

int main()
{
	init();

	initnow();
	circle(1);
	if (check())
	{
		fout<<1<<endl;
		return 0;
	}
	
	initnow();
	circle(2);
	if (check())
	{
		fout<<2<<endl;
		return 0;
	}
	
	initnow();
	circle(3);
	if (check())
	{
		fout<<3<<endl;
		return 0;
	}
	
	fanshe();
	if (check())
	{
		fout<<4<<endl;
		return 0;
	}
	
	initnow();
	fanshe();
	circle(1);
	if (check()) {fout<<5<<endl; return 0;}
	fanshe();
	circle(2);
	if (check()) {fout<<5<<endl; return 0;}
	fanshe();
	circle(3);
	if (check()) {fout<<5<<endl; return 0;}
	
	
	initnow();
	if (check())
	{
		fout<<6<<endl;
		return 0;
	}
	
	fout<<7<<endl;	
	return 0;
}

Tags: usaco c++
评论(1) 阅读(1358)

字符串快速排序 按字典序進行排序

2011年9月19日 02:46

各種OI測評系統中經常出現對字符串進行排序的題,以前我不太會字符串快排,結果都是用字典樹的遍歷進行的,現在終於會用qsort函數了,再次分享:

 

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
int cmp(const void *a, const void *b) {
	return strcmp((*(string*)a).data(),(*(string*)b).data());
}
string s[103];
int n;
int main() 
{
	freopen("letter.in", "r", stdin);
	freopen("letter.out", "w", stdout);
	cin >> n;
	for(int i=0; i<=n; i++)
		getline(cin, s[i]);
	qsort(s+1, n+1, sizeof(string), cmp);
	for(int i=2; i<=n+1; i++)
		printf("%s\n", s[i].c_str());
	return 0;
}

Tags: c++ 快速排序
评论(5) 阅读(1661)