---恢复内容开始---
这是2012noip普及组的一个模拟题,第一次得了50,看了题解后剪枝拿到100.
N层楼,m个房间,逆时针排序。每个房间有一个指示牌,也可能有楼梯,找到第(上楼的第一个房间指示牌)有楼梯的房间,上去,这些指示牌的数之和则为答案。所以先循环层数,再记录sum,并确定j=start和需要找几个有楼梯的,然后while房间数,找到了book++,如果绕了一圈,那么j=1。那么这里就有一个可以优化的地方了。当指示牌的要求大于这一层的房间数的时候,进行取余操作(a[i][start]-1)%f[i]+1,前面再计算每一层的数组即可。
1.数组一定要开满,编译没爆开就行。
2.细节错误的话,调试很重要,输出一定要完整。
3.时间复杂度高的话一定要有意识去优化暴力的方法,比如此处的取余。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> using namespace std; int n,m; int flag[100000][1000];//0没有 int a[100000][1000]; int f[1000001]; long long sum=0; int start; int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>flag[i][j]>>a[i][j]; f[i]=f[i]+flag[i][j]; } } cin>>start; start++;//从1开始 for(int i=1;i<=n;i++){ sum+=a[i][start]; int j=start;//上去的房间号 int book=0; a[i][start]=(a[i][start]-1)%f[i]+1; while(true){ if(flag[i][j]==1){ book++; // cout<<i<<" "<<j<<" "<<book<<endl; } if(book==a[i][start]){//! start=j; break; } else{ if(j<m) j++; else j=1; } } } cout<<sum%20123; return 0; }