本文原创,如果有不到位的地方欢迎通过右下角的按钮私信我!
A.Icow Player
题目描述
被无止境的农活压榨得筋疲力尽后,Farmer John打算用他在MP3播放器市场新买的iCow来听些音乐,放松一下。FJ的iCow里存了N(1 <= N <= 1,000)首曲子,按1..N依次编号。至于曲子播放的顺序,则是按一个Farmer John自己设计的算法来决定:
* 第i首曲子有一个初始权值R_i(1 <= R_i <= 10,000)。
* 当一首曲子播放完毕,接下来播放的将是所有曲子中权值最大的那首(如果有两首或多首曲子的权值相同,那么这些曲子中编号最小的那首会被选中)。
* 一首曲子在播放结束后,它的权值会被平均地分给其他N-1首曲子,它本身的权值清零。
* 如果一首曲子的权值无法被平均分配(也就是说,无法被N-1整除),那么被N-1除的余数部分将会以1为单位,顺次分配给排名靠前的曲子(也就是说,顺序为曲目1、曲目2...依次下去。当然,刚播放过的那首曲子需要被跳过),直到多出的部分被分配完。
在选定的下一首曲子播放完毕后,这个算法再次被执行,调整曲子的权值,并选出再接下来播放的曲目。
请你计算一下,按FJ的算法,最先播放的T(1 <= T <= 1000)首曲子分别是哪些。
输入
第1行: 2个用空格隔开的整数:N 和 T
第2..N+1行: 第i+1行为1个整数:R_i
输出
第1..T行: 第i行为1个整数,表示iCow播放的第i首曲子
样例输入
3 4
10
8
11
样例输出
3
1
2
3
题目总结
这道题拿到之后最先想到的就是模拟,于是我大致把程序拆分成了个部分——输入、播放、分配和输出。其中输入就不再赘述,播放部分每次播放权值最大的一首,所以每次都要找到权值最大的一首歌。在这里我犯了一个非常严重的错误——对所有数据进行排序,而且我担心复杂度过高,于是以n为周期每n次播放排序一次,这也是我后面只得10分的原因。
错误部分代码:
for(int i=1;i<=t;i++){ if(i%n==1)sort(a+1,a+1+n,cmp);//每n次播放排序一次 if(i%n==0)cout<<a[n].bh<<endl;//防止出现n倍数次循环出现下标为零的情况 else cout<<a[i%n].bh<<endl; int sum1=a[i%n==0?n:i%n].r/n-1;//下面是分配部分代码 ,一堆玄学三目运算符 int sum2=a[i%n==0?n:i%n].r%n-1; for(int j=1;j<=n;j++){ if(j==i%n==0?n:i%n)continue; a[j].r+=sum1; } s:; if(sum2>n){ for(int j=1;j<=n;j++){ if(j==i%n==0?n:i%n)continue; a[j].r++; } sum2-=n-1; goto s; } for(int j=1;j<=sum2;j++){ if(j==i%n==0?n:i%n)continue; a[j].r++; } }
AC代码:
#include<bits/stdc++.h> using namespace std; struct node{ int v; int d; } a[1005]; //结构体方便比较权值大小,也方便查找数据的编号; int main(){ int n,t; int i,r,max,num,k,id; cin>>n>>t; for(i=1; i<=n; i++){ cin>>a[i].v; a[i].d=i; } while(t--){ max=0; for(i=1; i<=n; i++) //比较权值的大小 if(a[i].v>max){ max=a[i].v; id=a[i].d; } cout<<id<<endl;//每次输出权值最大的歌曲的编号 num=a[id].v;//分配部分 k=num/(n-1); //平分播放了的歌曲的权值; r=num%(n-1);//除不尽小数部分化为整数1分给最近的歌曲权值; a[id].v=0; for(i=1; i<=n; i++){ if(i!=id)a[i].v+=k; } for(i=1; i<=r; i++){ if(i==id) r++; else a[i].v+=1; } } return 0; }
B.Costume
题目描述
万圣节又到了!Farmer John打算带他的奶牛去参加一个化装晚会,但是,FJ只做了一套能容下两头总长不超过S(1 <= S <= 1,000,000)的牛的恐怖服装。FJ养了N(2 <= N <= 20,000)头按1..N顺序编号的奶牛,编号为i的奶牛的长度为L_i(1 <= L_i <= 1,000,000)。如果两头奶牛的总长度不超过S,那么她们就能穿下这套服装。
FJ想知道,如果他想选择两头不同的奶牛来穿这套衣服,一共有多少种满足条件的方案。
输入
第1行: 2个用空格隔开的整数:N 和 S
第2..N+1行: 第i+1为1个整数:L_i
输出
第1行: 输出1个整数,表示FJ可选择的所有方案数。注意奶牛顺序不同的两种 方案是被视为相同的。
样例输入
4 6
3
5
2
1
样例输出
4
提示
【输出说明】 4种选择分别为:奶牛1和奶牛3;奶牛1和奶牛4;奶牛2和奶牛4;奶牛3和奶牛4。
题目总结
看大佬们的都是做的分治,但数据规模只有n<=20,000,所以直接暴力枚举所有可能然后判断可不可以装下就行了
AC代码:
#include<bits/stdc++.h> using namespace std; int n,s,l[20001],ans; int main(){ freopen("costume.in","r",stdin); freopen("costume.out","w",stdout); cin>>n>>s; for(int i=1;i<=n;i++){ cin>>l[i]; } for(int i=1;i<n;i++){ for(int j=i+1;j<=n;j++){ if(l[i]+l[j]<=s)ans++; } } cout<<ans; return 0; }
C.Contest
题目描述
FJ的N(1 <= N <= 100)头奶牛们最近参加了场程序设计竞赛:)。在赛场上,奶牛们按1..N依次编号。每头奶牛的编程能力不尽相同,并且没有哪两头奶牛的水平不相上下,也就是说,奶牛们的编程能力有明确的排名。
整个比赛被分成了若干轮,每一轮是两头指定编号的奶牛的对决。如果编号为A的奶牛的编程能力强于编号为B的奶牛(1 <= A <= N; 1 <= B <= N; A != B),那么她们的对决中,编号为A的奶牛总是能胜出。
FJ想知道奶牛们编程能力的具体排名,于是他找来了奶牛们所有M(1 <= M <= 4,500)轮比赛的结果,希望你能根据这些信息,推断出尽可能多的奶牛的编程能力排名。比赛结果保证不会自相矛盾。
输入
第1行: 2个用空格隔开的整数:N 和 M
第2..M+1行: 每行为2个用空格隔开的整数A、B,描述了参加某一轮比赛的奶牛的编号,以及结果(编号为A,即为每行的第一个数的奶牛为胜者)
输出
第1行: 输出1个整数,表示排名可以确定的奶牛的数目
样例输入
5 5
4 3
4 2
3 2
1 2
2 5
样例输出
2
提示
【输出说明】 编号为2的奶牛输给了编号为1、3、4的奶牛,也就是说她的水平比这3头奶 牛都差。而编号为5的奶牛又输在了她的手下,也就是说,她的水平比编号为5的 奶牛强一些。于是,编号为2的奶牛的排名必然为第4,编号为5的奶牛的水平必 然最差。其他3头奶牛的排名仍无法确定。
题目总结
这道题我直接全做错了然后卡了10分
我的错误思路是:如果有了a,b比赛的结果,就可以判断a,b的关系,如果一个人可以和其他n-1人的关系都确定,答案数就加一
错误代码:
#include<bits/stdc++.h> using namespace std; int win[101][101],n,m,a,b,ans,flag; int main(){ freopen("contest.in","r",stdin); freopen("contest.out","w",stdout); cin>>n>>m; for(int i=1;i<=m;i++){ cin>>a>>b; win[a][b]=win[b][a]=1; } for(int i=1;i<=n;i++){ flag=0; for(int j=i+1;j<=n;j++){ if(win[i][j]==0){ flag=1;break; } } if(flag==0)ans++; } cout<<ans; return 0; }
正确的做法是用Floyed,用一个二维数组存储比赛结果,然后三重循环枚举k、i、j,判断i==j?,然后判断win[i][k]是否为i,win[k][j]是否为k,如果全部满足的就把win[i][j]和win[j][i]设为i,最后判断是不是和其他人都比赛过了,如果是的话就答案数增加
AC代码:
#include<iostream> #include<cstdio> using namespace std; int a,b,n,m,f[101][101],ans; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d",&a,&b); f[a][b]=1; } for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=f[i][j]|f[i][k]&f[k][j]; for(int i=1;i<=n;i++){ int gg=1; for(int j=1;j<=n;j++) if(i==j)continue;else gg=gg&(f[i][j]|f[j][i]); ans+=gg; } printf("%d\n",ans); }
D.Cowrun
题目描述
奶牛们打算通过锻炼来培养自己的运动细胞,作为其中的一员,贝茜选择的运动方式是每天进行N(1 <= N <= 10,000)分钟的晨跑。在每分钟的开始,贝茜会选择下一分钟是用来跑步还是休息。
贝茜的体力限制了她跑步的距离。更具体地,如果贝茜选择在第i分钟内跑步,她可以在这一分钟内跑D_i(1 <= D_i <= 1,000)米,并且她的疲劳度会增加1。不过,无论何时贝茜的疲劳度都不能超过M(1 <= M <= 500)。如果贝茜选择休息,那么她的疲劳度就会每分钟减少1,但她必须休息到疲劳度恢复到0为止。在疲劳度为0时休息的话,疲劳度不会再变动。晨跑开始时,贝茜的疲劳度为0。
还有,在N分钟的锻炼结束时,贝茜的疲劳度也必须恢复到0,否则她将没有足够的精力来对付这一整天中剩下的事情。
请你计算一下,贝茜最多能跑多少米。
输入
第1行: 2个用空格隔开的整数:N 和 M
第2..N+1行: 第i+1为1个整数:D_i
输出
第1行: 输出1个整数,表示在满足所有限制条件的情况下,贝茜能跑的最大距离
样例输入
5 2
5
3
4
2
10
样例输出
9
提示
【输出说明】 贝茜在第1分钟内选择跑步(跑了5米),在第2分钟内休息,在第3分钟内跑 步(跑了4米),剩余的时间都用来休息。因为在晨跑结束时贝茜的疲劳度必须 为0,所以她不能在第5分钟内选择跑步。
题目总结
这道题我根本就没看懂
AC代码:
#include<bits/stdc++.h> #define MAXN 11111 #define MAXM 555 #define INF 1000000007 using namespace std; int dp[MAXN][MAXM]; int a[MAXN]; int n, m; int main() { scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n; i++) { dp[i][0] = dp[i - 1][0]; for(int j = 1; j <= m; j++) { if(i >= j) dp[i][0] = max(dp[i][0], dp[i - j][j]); dp[i][j] = max(dp[i - 1][j - 1] + a[i], dp[i][j]); } } printf("%d\n", dp[n][0]); return 0; }