P1076寻宝

---恢复内容开始---

这是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;
}
原文地址:https://www.cnblogs.com/china-mjr/p/11339874.html