tks

24
TKS 1 第第第第第第 () 第第第第第第 () 第第第第 第第第第第 、、 第第第第 第第第第第 、、 第第第第第第第 第第第 第第第第第第第 第第第 ( ( 第第第第第 第第第第第 ) ) 第第第第第第 第第第第第第 第第第第第第第第第第第第 第第第第第第第第第第第第

Upload: hu-pace

Post on 02-Jan-2016

22 views

Category:

Documents


1 download

DESCRIPTION

TKS. 1. 高级语言. (第二十六讲). ( 编程选讲八 ). 铺满方格、 最少失约 、 语文教师的困惑 、 放苹果. 绍兴文理学院. 计算机系计算机应用教研室. 例 1 铺满方格 [1041]. (n1+n2+n3)!. n1!n2!n3!. TKS. 2. 有 1×n 的一个长方形,用 1×1 、 1×2 、 1×3 的骨牌铺满方格。例如当 n=3 时为 1×3 的方格(如图),此时用 1×1 , 1×2 , 1×3 的骨牌铺满方格,共有四种铺法。. Input 多组测试,每组一个整数 n ( 1

TRANSCRIPT

TKS 1

(第二十六讲)(第二十六讲)

铺满方格、最少失约、铺满方格、最少失约、语文教师的困惑、放苹果语文教师的困惑、放苹果

(( 编程选讲八编程选讲八 ))

绍兴文理学院绍兴文理学院计算机系计算机应用教研室计算机系计算机应用教研室

InputInput多组测试,每组一个整数多组测试,每组一个整数 nn (( 1<=n<=501<=n<=50 ),输入到文件尾结),输入到文件尾结束。束。OutputOutput每组测试输出一行,表示铺法数。每组测试输出一行,表示铺法数。Sample InputSample Input112233Sample OutputSample Output112244

有有 1×n1×n 的一个长方形,用的一个长方形,用 1×11×1 、、 1×21×2 、、 1×31×3 的骨牌铺满方的骨牌铺满方格。例如当格。例如当 n=3n=3 时为时为 1×31×3 的方格(如图),此时用的方格(如图),此时用 1×11×1 ,, 1×21×2,, 1×31×3 的骨牌铺满方格,共有四种铺法。的骨牌铺满方格,共有四种铺法。

例例 1 1 铺满方格铺满方格 [1041][1041]

分析分析 11 ::当当 1×11×1 、、 1×21×2 、、 1×31×3 的骨牌分的骨牌分别有别有 n1n1 、、 n2n2 、、 n3n3 块时,则有块时,则有

(n1+n2+n(n1+n2+n3)!3)!n1!n2!n3!n1!n2!n3!

种铺法。种铺法。

TKS

2 04:08

分子也不要乘积,要用分母的各因子去除分子的个因子,使分子的积仅可能的小,最后再除分母可能有的大于 1 的因子。 结果或中间数据还可能出现 int 类型数据放不下的情况。其实,在测试数据中,最大的输出数据为: 10562230626642(14 位 )分析 3 :对于可能有较大的数值,可考虑用 __int64 类型的数据。 __int64 是 64 位整数,其数值范围为:

分析分析 22 ::对于对于 (n1+n2+n(n1+n2+n3)!3)!n1!n2!n3!n1!n2!n3!

否会溢出否会溢出 ,, 设设 n1+n2+n3=n,n1n1+n2+n3=n,n1 、、 n2n2 、、 n3n3 的最大值是的最大值是n1,n1, 则:则:(n1+n2+n(n1+n2+n

3)!3)!n1!n2!n3!n1!n2!n3!n(n-1)(n-n(n-1)(n-

2)┅(n1+1)2)┅(n1+1) n2!n3!n2!n3!

signed unsigned

-(263-1) ~ 263-1 0 ~ 224-1(18 446 744 073 709 551 615)

,, 要注意到计算过程中存储的数据是要注意到计算过程中存储的数据是

TKS

3 04:08

定义: __int64 a; 使用: scanf(“%I64d”,&a

); printf(“%I64d”,a);

定义: unsigned __int64 a; 使用: scanf(“%I64u”,&a)

; printf(“%I64u”,a);

分析 4 :用一函数来计算 的值。(n1+n2+n(n1+n2+n3)!3)!n1!n2!n3!n1!n2!n3!

fact(n3,n3,n1)#include<iostream>using namespace std;__int64 fact(int a,int b,int c){unsigned __int64 sum; int s[50],s1[50],s2[50],n,i,j,m,a1,b1,t; if(a>b) {t=a;a=b;b=t;} if(a>c) {t=a,a=c;c=t;} if(b>c) {t=b;b=c;c=t;} n=m=a+b+c;a1=a;b1=b;

TKS

4 04:08

for(i=0;i<n-c;i++) s[i]=m--;for(i=0;i<b-1;i++) s1[i]=b1--;

for(i=0;i<a-1;i++) s2[i]=a1--;for(i=0;i<n-c;i++)

{for(j=0;j<b-1;j++) if(s[i]%s1[j]==0&&s1[j]>1) {s[i]=s[i]/s1[j];s1[j]=1;}

for(j=0;j<a-1;j++) if(s[i]%s2[j]==0) {s[i]=s[i]/s2[j];s2[j]=1;} }

sum=1;for(i=0;i<n-c;i++) sum=sum*s[i];

for(j=0;j<b-1;j++) if(s1[j]>1&&sum%s1[j]==0) sum=sum/s1[j];for(j=0;j<a-1;j++) if(s2[j]>1&&sum%s2[j]==0) sum=sum/s2[j];return sum;

} TKS

5 04:08

int main(){ int n,n3,n2,n1,i,j;

unsigned __int64 t;while(cin>>n){n3=n/3;t=0; for(i=n3;i>=0;i--) {n2=(n-i*3)/2; for(j=n2;j>=0;j--) {n1=n-i*3-j*2;

t=t+fact(i,j,n1); }

} printf("%I64u\n",t);}

return 0;}

例 1 铺满方格 [1041] C+26_1 例 1 铺满方格 [1041] C+26_1 testoutput12471324448114927450492717053136576810609

testinput12345678910111213141516

302928272625242319404245504849

5379808029249425159025918646064470077025557571389537755476660122383752772

98064177867

45017743172

411056223062

66423122171529

2335742568741

225

TKS

6 04:08

c+26_1.cpp

分析与思考的收获分析与思考的收获

得:得: f(n)=f(n-1)+f(n-2)+f(n-3)f(n)=f(n-1)+f(n-2)+f(n-3)

1×n1×n 的一个长方形用的一个长方形用 1×11×1 ,, 1×21×2 ,, 1×31×3 的骨牌铺满方格,共的骨牌铺满方格,共包含以下三种情况:包含以下三种情况:

…………

f(n-1)f(n-1)

…………

…………

f(n-2)f(n-2)

f(n-3)f(n-3)

#include <iostream>#include <iostream>using namespace std ;using namespace std ;__int64 f(int n)__int64 f(int n){if(n==1) return 1;{if(n==1) return 1; if(n==2) return 2;if(n==2) return 2; if(n==3) return 4;if(n==3) return 4; return f(n-1)+f(n-2)+f(n-3);return f(n-1)+f(n-2)+f(n-3);}}int main()int main(){ int n;{ int n; while(cin>>n)while(cin>>n) printf( "%I64d\n", f(n));printf( "%I64d\n", f(n)); return 0 ;return 0 ;}}

例 1 铺满方格的第二种解法 C+26_1_1 例 1 铺满方格的第二种解法 C+26_1_1

TKS

7 04:08

C+26_1_1.cpp

#include<iostream>#include<iostream>using namespace std;using namespace std;int main()int main(){__int64 s[51]={0,1,2,4};{__int64 s[51]={0,1,2,4}; int n,i;int n,i; for(i=4;i<=50;i++)for(i=4;i<=50;i++) s[i]=s[i-1]+s[i-2]+s[i-3];s[i]=s[i-1]+s[i-2]+s[i-3]; while(cin>>n)while(cin>>n) printf("%I64d\n",s[n]);printf("%I64d\n",s[n]); return 0;return 0;}}

例 1 铺满方格的第三种解法 C+26_1_2 例 1 铺满方格的第三种解法 C+26_1_2

还是分析与思考的收获还是分析与思考的收获 避免重复计算,事先算好各避免重复计算,事先算好各 f(n)f(n) 的值。的值。

TKS

8 04:08

c+26_1_2.cpp

把 M 个同样的苹果放在 N 个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法(不同的分法用 K 表示)? 5 , 1, 1 和 1 , 5 , 1 是同一种分法。Input 第一行是测试数据的数目 t ( 0 <= t <= 20 )。以下每行均包含二个整数 M 和 N ,以空格分开。 1<=M , N<=10 。Output 对输入的每组数据 M 和 N ,用一行输出相应的 K 。Sample Input17 3Sample Output8

例例 2 2 放苹果放苹果 [1022][1022]

TKS

9 04:08

对于对于 m=7,n=3m=7,n=3 的情况,有以下几种可能的放法:的情况,有以下几种可能的放法: 0 0 7 0 1 6 0 2 5 0 3 4 1 1 5 1 2 4 1 3 3 2 2 3

分析分析

先确定第一个 ( 也就是任意一个 ) 盘中放苹果的数量,从最少 (0) 开始,由于不同盘中相同数量的苹果数是同一种放法,故,第一个盘中放苹果的数量只要考虑到从 0 个到 m/n 个即可; 由于后面盘中放的苹果数只要考虑不比在盘中已经放了的苹果数就可以了,设第一个盘中放了 i 个苹果,则还有 m-i 个苹果放在 n-1 个盘里,注意到前面的盘中已经放了 i 个苹果,后面的盘中要放的苹果数不比 i 小,即求函数 f(m-i , n-1 , i) 的值,在 f(m-i, n-1 , i) 中其方法是一样的。 所以对于 0≤i≤m/n ,可以写一个递归函数 f(m-i , n-1 , i) 实现之。

TKS

10 04:08

#include<iostream>using namespace std;int f(int m,int n,int p){ int k,i,s=0; if(n==1) return 1; k=m/n; for(i=p;i<=k;i++)

s=s+f(m-i,n-1,i); return s;}

int main(){int i,n,m,c,t,k,s; cin>>t; for(c=0;c<t;c++) {cin>>m>>n; if(n==1) {printf("1\n");continue;} k=m/n;s=0; for(i=0;i<=k;i++) s=s+f(m-i,n-1,i); printf("%d\n",s); } return 0;}

例 2 放苹果 [1022] C+26_2 例 2 放苹果 [1022] C+26_2

测试数据 C+26_2.DOC测试数据 C+26_2.DOC

TKS

11 04:08

c+26_2.cpp

c+26_2.doc

例 3 数字螺旋方阵 已知 16 个数字的螺旋方阵的形式如下所示。 16 15 14 13 5 4 3 12 6 1 2 11 7 8 9 10 输入数据的第一行为一个正整数 T, 表示测试数据的组数。然后是 T组测试数据。对于输入的 n(n<=20),请输出 n×n 的螺旋方阵。各列按 4 位宽度输出。Input 输入数据的第一行为一个正整数 T, 表示测试数据的组数 . 然后是 T组测试数据。每组测试数据一个正整数 n 。Output 输出 n×n 的数字螺旋方阵。各列按 4 位宽度输出。

TKS

12 04:08

Sample Input25 6Sample Output 25 24 23 22 21 10 9 8 7 20 11 2 1 6 19 12 3 4 5 18 13 14 15 16 17 36 35 34 33 32 31 17 16 15 14 13 30 18 5 4 3 12 29 19 6 1 2 11 28 20 7 8 9 10 27 21 22 23 24 25 26

TKS

13 04:08

int main(){int n,i,j,k,d,m,t,p,a[26][26]; cin>>t; for(p=0;p<t;p++) {cin>>n; for(i=1;i<=25;i++) for(j=1;j<=25;j++) a[i][j]=0; m=(n+1)/2;k=n*n+1; for(d=1;d<=m;d++) //圈数 {i=d; //上面一行 for(j=d;j<=n+1-d;j++) {k--; a[i][j]=k; } j=n-d+1; //右面一列 for(i=d+1;i<=n+1-d;i++) {k--; a[i][j]=k; }

i=n-d+1; // 下面一行 for(j=n-d;j>=d;j--) {k--; a[i][j]=k; } j=d; //左面一列 for(i=n-d;i>=d+1;i--) {k--; a[i][j]=k; } } for(i=1;i<=n;i++) // 输出 {for(j=1;j<=n;j++) printf("%4d",a[i][j]); printf("\n"); } } return 0;}

例 3 数字螺旋方阵 C+26_3

例 3 数字螺旋方阵 C+26_3

TKS

14 04:08

C+26_3.cpp

例例 4 4 语文教师的困惑 语文教师的困惑 [1027][1027] ACM星球上的单词至少由 4 个字母组成 ,并且规定 : 构成单词的字母必须是不降序的 , 即对于单词W1W2…Wn,必须满足W1<=W2<=…<=Wn( 由 ACSII顺序决定大小关系 ) 。满足这些条件的单词就一定是合法的。例如 :ACMR,ABCDEFXZ是合法单词 ,而ACM,ACMER则不是合法单词。 作为语文教师的你 ,需要经常修改学生的作业。当然 , 考虑到教师的工作量 ,你只需要划去若干字母 , 使得剩下的每个单词能符合合法性规定即可。给你一个句子 , 现在请你判断 , 最少需要删除多少字母 ,才符合语法要求。Input 有多组测试 . 对于每组测试 ,首先是整数 n(n>0),然后是 n 个需要你处理的单词 (单词之间由一个空格分隔 , 其余全部由大写英文字母构成 , 不含其他符号 ) 。Output 对于每组测试 , 输出需要删除的最少字母数量。

Sample Output3035

Sample Input3 ACMER IS ABCXYZ4 ABCD EFGH EFFGH ABCD4 EFGH EFEGH ABCDXY QWERTY2 ABCA X TK

S15 04:08

分析:1 、正确的输入:可用常规办法— cin 方式输入数据;2 、编写一个函数来计算单词中要删除的字符数;3 、从局部到全部的方法来计算要删除的字符数: if(str[j]<=str[i])

d[i]=max(d[i],d[j]+1); str 为单词的字符串; d[i] 为 str 中下标为 i 的字符符合字母顺序的字母个数; 0≤i≤strlen-1, 0≤j≤i-1 ; // 从局部到全部的核心方法

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

int max(int a,int b){return a>b?a:b;}

TKS

16 04:08

int fun(char str[]){ int i,j,len,d[200],ma; len=strlen(str); if(len<4) return len; d[0]=1;ma=1; for(i=1;i<len;i++) {d[i]=1; for(j=0;j<i;j++)

if(str[j]<=str[i]) d[i]=max(d[i],d[j]+1);

ma=max(ma,d[i]); } if(ma<4) return len; return len-ma;}

int main(){int n,i,sum; char s[200]; while(cin>>n) {sum=0; for(i=0;i<n;i++) {cin>>s; sum=sum+fun(s); } printf("%d\n",sum); } return 0;}

例 4 语文教师的困惑 [1027] C+26_4 例 4 语文教师的困惑 [1027] C+26_4

测试数据 C+26_4.DOC测试数据 C+26_4.DOC

TKS

17 04:08

C+26_4.doc

c+26_4.cpp

例例 5 5 又见最少失约又见最少失约 [1246][1246] 我们明年将有许多重要的活动需要参加,可是由于活动太多,无法全部参加,请你帮我们安排,以便更有效地参加活动,使得参加活动的价值总和最大。现在给出明年的全部活动的开始日期和结束日期,并给出这些活动对应的价值,请你计算能够得到的最大价值。 注意,由于活动是以天为基本单位,因此 , 能够参加的相邻两个活动必须满足:第二个活动的开始日期要晚于第一个活动的结束日期。Input 输入数据首先包含一个整数 T,表示测试实例的个数,然后是 T组测试数据。每组数据第一行为整数 n(1<=n<=300) ,代表有 n 个活动。以下的 n 行每行包括三个由空格隔开的整数 i,j,k ,其中 1<=i<=j<=365 , 0<k<100. 分别代表活动的开始日期、结束日期和价值。Output 对于每组测试数据,输出能够得到的最大价值总和,每组测试数据输出占一行。

Sample Input232 5 54 6 46 7 10

Sample Output1510

31 2 32 4 103 10 2

TKS

18 04:08

#include <iostream>using namespace std;struct val{int d1; int d2; int v; int m;};int max(int a,int b){return a>b?a:b;}int main(){int n,i,j,t,k,ma; val s[300],s1;

cin>>t; for(k=0;k<t;k++) {cin>>n; for(i=0;i<n;i++) cin>>s[i].d1>>s[i].d2>>s[i].v; for(i=0;i<n-1;i++) for(j=0;j<n-i-1;j++) if(s[j].d2>s[j+1].d2) {s1=s[j]; s[j]=s[j+1]; s[j+1]=s1; }

TKS

19 04:08

ma=s[0].m=s[0].v; for(i=1;i<n;i++) {s[i].m=s[i].v; for(j=0;j<i;j++) if(s[j].d2<s[i].d1) s[i].m=max(s[i].m,s[j].m+s[i].v); ma=max(ma,s[i].m); } printf("%d\n",ma); } return 0;}

例 5 又见最少失约 [1246] C+26_5 例 5 又见最少失约 [1246] C+26_5

测试数据 C+26_5.DOC测试数据 C+26_5.DOC

TKS

20 04:08

c+26_5.cpp

c+26_5.doc

给定给定 nn 种物品和种物品和 11 个背包,物品个背包,物品 ii 的重量是的重量是 wiwi ,其价值为,其价值为 vivi ,,背包的容量为背包的容量为 CC 。要求选择装入背包的物品,使得装入背包中物品。要求选择装入背包的物品,使得装入背包中物品的总价值最大。的总价值最大。InputInput 每组测试数据包含每组测试数据包含 33 行,第行,第 11 行为行为 nn 和和 cc ,表示有,表示有 n(0<=n<=4n(0<=n<=400)00) 个物品且背包容量为个物品且背包容量为 c (c<=1500)c (c<=1500) ,第二行为这,第二行为这 nn 个物品的重个物品的重量量 wi(1<=wi<=1000)wi(1<=wi<=1000) ,第三行为这,第三行为这 nn 个物品的价值个物品的价值 vivi 。背包容量。背包容量和物品重量都为整数。和物品重量都为整数。OutputOutput 输出装入背包的最大总价值,每个答案一行。输出装入背包的最大总价值,每个答案一行。

例例 6 0-16 0-1背包问题背包问题 [1006][1006]

Sample InputSample Input5 105 102 2 6 5 42 2 6 5 46 3 5 4 66 3 5 4 6

Sample Sample

OutputOutput1515

TKS

21 04:08

w[0]=2 m[10]=6 m[9]=6 m[8]=6 m[7]=6 m[6]=6 m[5]=6 m[4]=6 m[3]=6 m[2]=6 m[1]=0 w[1]=2 m[10]=9 m[9]=9 m[8]=9 m[7]=9 m[6]=9 m[5]=9 m[4]=9 m[3]=6 m[2]=6 m[1]=0 w[2]=6 m[10]=14 m[9]=11 m[8]=11 m[7]=9 m[6]=9 m[5]=9 m[4]=9 m[3]=6 m[2]=6 m[1]=0 w[3]=5 m[10]=14 m[9]=13 m[8]=11 m[7]=10 m[6]=9 m[5]=9 m[4]=9 m[3]=6 m[2]=6 m[1]=0 w[4]=4 m[10]=15 m[9]=15 m[8]=15 m[7]=12 m[6]=12 m[5]=9 m[4]=9 m[3]=6 m[2]=6 m[1]=0

分析: 分析: 设置数组设置数组 m[c]m[c] ,计算放入背包各容量,计算放入背包各容量 (( 重量重量 11 ~~ c)c) 的最大价值的最大价值;; 对于每一对重量和价值的物品,递推计算放入背包各重量为对于每一对重量和价值的物品,递推计算放入背包各重量为 jj 时时m[j](1≤j≤c)m[j](1≤j≤c) 的最大价值,要用逆序递推,否则会重复计算:的最大价值,要用逆序递推,否则会重复计算: for(i=0;i<n;i++)for(i=0;i<n;i++) for(j=c;j>=1;j--)for(j=c;j>=1;j--)

if(j>=w[i]) m[j]=max(m[j],m[j-w[i]]+v[i]);if(j>=w[i]) m[j]=max(m[j],m[j-w[i]]+v[i]);如:如: 5 105 10 2 2 6 5 42 2 6 5 4 6 3 5 4 66 3 5 4 6

各各 m[j]m[j] 值为: 值为:

最后最后 m[c]m[c] 中的值即为背包可容纳的最大价值。 中的值即为背包可容纳的最大价值。 TKS

22 04:08

#include<iostream>using namespace std;int max(int a,int b){return a>b?a:b;}int main(){int n,c,i,j,w[1000],v[1000],m[1501]; while(cin>>n>>c) {for(i=0;i<n;i++) cin>>w[i]; for(i=0;i<n;i++) cin>>v[i]; for(i=0;i<=c;i++) m[i]=0; for(i=0;i<n;i++) for(j=c;j>=1;j--) if(j>=w[i]) m[j]=max(m[j],m[j-w[i]]+v[i]); printf("%d\n",m[c]); } return 0;}

例 6 0-1背包问题 [1006] C+26_6 例 6 0-1背包问题 [1006] C+26_6

测试数据 C+26_6.DOC测试数据 C+26_6.DOC

TKS

23 04:08

c+26_6.cpp

c+26_6.doc

成功在于努力!