E. Balance Reset(交互 dp)

原题: http://codeforces.com/gym/101848/problem/E

题意:

有2n个菜有各自的价格,每天会随机给出n个菜供选择。你现在有p元,每天可以先充钱再吃一次饭,或者不吃。问能否在365天内使余额为0。

解析:

首先是交互题的要求,每次输入后都要输出一条,并且输出完后要刷新缓冲区。(直接endl或者加fflush(stdout)),在余额为0后直接exit(0)结束程序。

首先是可以无限次充钱(100为单位),所以-25=75,所以状态只有0~99了(100可以特判掉)。可以用bfs来维护到达每个点需要最少几步。

当一个状态可以转移到一个步数较少的状态就直接转移。因为必定存在一个菜使得一个状态往更少的状态转移,且出现的概率至少1/2,所以不用担心365天后完不成。

#include<bits/stdc++.h>
using namespace std;
#define ll long long

int a[2009];
int dp[2009];
bool vis[2009];

int main(){
    int n,p;
    cin>>n>>p;
    for(int i=1;i<=2*n;i++)cin>>a[i];
    queue<int>Q;
    vis[0]=1;
    dp[0]=0;
    Q.push(0);

    while(!Q.empty()){
        int u=Q.front();Q.pop();
        for(int i=1;i<=2*n;i++){
            int v=(u+a[i])%100;
            if(vis[v])continue;
            vis[v]=1;
            dp[v]=dp[u]+1;
            Q.push(v);
        }
    }

    int res=p;
    for(int ii=1;ii<=365;ii++){
        int now[1009];
        for(int i=1;i<=n;i++)scanf("%d",&now[i]);
        if(res==100){
            cout<<0<<' '<<now[1]<<endl;
            res-=a[now[1]];
            if(res==0)exit(0);
            continue;
        }
        int have=0;
        for(int i=1;i<=n;i++){
            int to=(res-a[now[i]]+100)%100;
            if(dp[to]<dp[res]){
                int ans=0;
                if(res-a[now[i]]<0)ans++;
                cout<<ans<<' '<<now[i]<<endl;
                have=1;
                res=to;
                i=n;
            }
        }
        if(!have){
            cout<<0<<' '<<0<<endl;
        }
        if(res==0)exit(0);
    }
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/90137626