清華大學2011年複試上機題 解題報告

九度OJ 題目1088:剩下的樹
時間限制:1 秒  內存限制:32 兆  特殊判題:否  提交:929  解決:328
題目描述:
        有一個長度爲整數L(1<=L<=10000)的馬路,可以想象成數軸上長度爲L的一個線段,起點是座標原點,在每個整數座標點有一棵樹,即在0,1,2,...,L共L+1個位置上有L+1棵樹。
        現在要移走一些樹,移走的樹的區間用一對數字表示,如 100 200表示移走從100到200之間(包括端點)所有的樹。
        可能有M(1<=M<=100)個區間,區間之間可能有重疊。現在要求移走所有區間的樹之後剩下的樹的個數。
輸入:
        兩個整數L(1<=L<=10000)和M(1<=M<=100)。
        接下來有M組整數,每組有一對數字。
輸出:
        可能有多組輸入數據,對於每組輸入數據,輸出一個數,表示移走所有區間的樹之後剩下的樹的個數。
樣例輸入:
    500 3
    100 200
    150 300
    470 471
樣例輸出:
    298
//清華2011:題目1088:剩下的樹 
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <fstream>
using namespace std;
struct TREE{
	int x;
	int y;
};
TREE t[100];
bool f[10001];

int main(){
	int l, m,
		i, j, k, n;
	ifstream cin("THU_1088.txt"); 
	while( cin >> l ){
		memset( f, 0, sizeof(f) );
		cin >> m;
		for( i=0; i<m; i++ ){
			cin >> t[i].x >> t[i].y;
			if( t[i].x > t[i].y ){
				int temp = t[i].x;
				t[i].x = t[i].y;
				t[i].y = temp;
			}
			for( j=t[i].x; j<=t[i].y; j++ )
				f[j] = 1;
		}

		int num=0;
		for( i=0; i<=l; i++ )
			if( f[i]==1 )
				num++;

		cout << l+1-num << endl;
	}
	system("pause");
	return 0;
}
更新個更高效的解法(去年做有bug 今年一次就搞定了)
#include <fstream>
#include <algorithm>
#include <iostream>
using namespace std;
struct TREE{int x,y;};
TREE t[100],f[100];
bool cmp( TREE a, TREE b ){ return a.x < b.x; };
int main(){
	int i, j, k, l, n, m;
	ifstream cin("THU_1088.txt"); //

	while( cin >> l >> m ){
		for( i=0; i<m; i++ ){
			cin >> t[i].x >> t[i].y;
			if( t[i].x > t[i].y ){
				int temp = t[i].x;
				t[i].x = t[i].y;
				t[i].y = temp;
			}
		}
		sort( t, t+m, cmp );	//按y 即區間左端點升序排序

		f[0] = t[0];
		for( i=1,j=0; i<m; i++ ){
			//cout << t[i].x << " " << t[i].y << endl;
			if( t[i].x - 2 < f[j].y ){	//區間需合併
				f[j].y = max( f[j].y, t[i].y );
			}else{	//區間不合並
				f[++j] = t[i];
			}
		}

		int num = 0;
		for( i=0; i<=j; i++ ){
			//cout << f[i].x << " " << f[i].y << endl;
			num += ( f[i].y - f[i].x + 1 );
		}

		cout << l+1-num << endl;
	}
	return 0;
}


九度OJ 題目1087:約數的個數
時間限制:1 秒  內存限制:32 兆  特殊判題:否  提交:1596  解決:382
題目描述:
    輸入n個整數,依次輸出每個數的約數的個數
輸入:
    輸入的第一行爲N,即數組的個數(N<=1000)
    接下來的1行包括N個整數,其中每個數的範圍爲(1<=Num<=1000000000)
    當N=0時輸入結束。
輸出:
    可能有多組輸入數據,對於每組輸入數據,
    輸出N行,其中每一行對應上面的一個數的約數的個數。
樣例輸入:
    5
    1 3 4 6 12
樣例輸出:
    1
    2
    3
    4
    6
//清華2011:題目1087:約數的個數 
#include <iostream>
using namespace std;
struct DIVISOR{
	int x;
	int y;
};
DIVISOR d[200];

int main(){
	int i, j, k, n, m, t;
	while( cin >> n && n!=0 ){
		while( n-- ){
			for( i=0; i<200; i++ )	//初始化
				d[i].x = d[i].y = 0;
			cin >> m;
			j = 0;	//記錄d[i]當前使用中的下標
			for( i=2; i*i<=m || m!=1; ){
				if( m%i == 0 ){
					if( i != d[j].x ){
						j++;
						d[j].x = i;
					}
					d[j].y++;
					m /= i;
				}
				else i++;
			}
			int result = 1;
			for( i=1; d[i].x!=0; i++ ){
				//cout << d[i].x << " " << d[i].y << endl;
				result *= (d[i].y+1);
			}

			cout << result << endl;
		}

	}
	//system("pause");
	return 0;
}


九度OJ 題目1086:最小花費
時間限制:1 秒  內存限制:32 兆  特殊判題:否  提交:765  解決:121
題目描述:
    在某條線路上有N個火車站,有三種距離的路程,L1,L2,L3,對應的價格爲C1,C2,C3.其對應關係如下:
    距離s           票價
    0<S<=L1         C1
    L1<S<=L2        C2
    L2<S<=L3        C3
    輸入保證0<L1<L2<L3<10^9,0<C1<C2<C3<10^9。
    每兩個站之間的距離不超過L3。
    當乘客要移動的兩個站的距離大於L3的時候,可以選擇從中間一個站下車,然後買票再上車,所以乘客整個過程中至少會買兩張票。
    現在給你一個 L1,L2,L3,C1,C2,C3。然後是A B的值,其分別爲乘客旅程的起始站和終點站。
    然後輸入N,N爲該線路上的總的火車站數目,然後輸入N-1個整數,分別代表從該線路上的第一個站,到第2個站,第3個站,……,第N個站的距離。
    根據輸入,輸出乘客從A到B站的最小花費。
輸入:
    以如下格式輸入數據:
    L1  L2  L3  C1  C2  C3
    A  B
    N
    a[2]
    a[3]
    ……
    a[N]
輸出:
    可能有多組測試數據,對於每一組數據,
    根據輸入,輸出乘客從A到B站的最小花費。
樣例輸入:
    1 2 3 1 2 3
    1 2
    2
    2
樣例輸出:
    2
//清華2011:題目1086:最小花費
//0<L1<L2<L3<10^9  0<C1<C2<C3<10^9
// 每兩個站之間的距離<=L3
//A-B是起-終點站 n是站點數 即a[]有n-1個元素爲a[2]-a[n]
//a[]分別代表從該線路上的第1個站,到第2個站,第3個站,……,第N個站的距離。
//	以如下格式輸入數據:
//	L1  L2  L3  C1  C2  C3
//	A  B
//	N
//	a[2]
//	a[3]
//	……
//	a[N]
#include <fstream>
#include <cstdio>
#include <iostream>
#define T 100000
#define INT long long
using namespace std;
INT a[T], b[T], l[4], c[4];	//l[0]捨棄不用以便對齊題幹
INT dp[T], t[4];
int back[4];	//back[0]亦捨棄不用
int A, B;

void backward( int x, int index ){	//x爲向後搜時的起點站號
	INT sum = 0;
	back[index] = x+1;
	for( int i=1; sum<=l[index]; i++ ){
		sum = a[x] - a[x-i];
		back[index]--;
		if( back[index] < A )
			back[index] = A;
	}
};

int main()
{
	int i, j, k, n;
	freopen("THU_1086.txt","r",stdin);//
	while( scanf("%d%d%d%d%d%d", &l[1],&l[2],&l[3],&c[1],&c[2],&c[3])!=EOF ){
		scanf( "%d%d%d", &A, &B, &n );
		a[0] = a[1] = 0;
		for( i=2; i<=n; i++ )
			scanf( "%d", &a[i]);	//%f讀浮點數
		if( A > B ){
			int temp = A;
			A = B;
			B = temp;
		}else if( A == B ){
			printf("0\n");
			continue;
		}
		for( i=0; i<=A; i++ )	//初始化 dp[0]dp[1]是虛構的無意義的初始數值
			dp[i] = 0;
		for( i=A+1; i<=B; i++ ){
			k = 0;	//k記錄t[]中有效數據的個數
			for( j=1; j<=3; j++ ){
				backward( i, j );
				if( back[j] != i )
				{ k++; t[k] = dp[back[j]]+c[j]; }
			}
			for( j=1; j<=k-1; j++ )
				t[1] = min( t[1], t[j+1] );	//更改t[1]獲得最小值
			dp[i] = t[1];
		}
		printf( "%lld\n", dp[B] );
	}
	//while(1);//
	return 0;
}


發佈了43 篇原創文章 · 獲贊 4 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章