[noip 2016] 교실 바 꾸 기 문제 풀이

사실 noip 시험 기간 은 아주 좋 습 니 다. 하지만 기대 하 는 지식 을 조금 만 알 면 만 들 수 있 습 니 다.
고려 하 다두 교실 사이 의 최 단 로 는 플 로 이 드 로 미리 처리 할 수 있 고 나중에 O (1) 로 사용 하면 된다.상태 f [i] [j] [0... 1] 은 앞 i 칸 교실, j 칸, i 칸 바 뀌 지 않 겠 다 는 기 대 를 나타 낸다.
모든 상 태 는 이렇게 업데이트 할 수 있 습 니 다. dp [i] [j] [0] = min (dp [i] [0], dp [i - 1] [j] [0] + (double) dis [c [i]] [c [i - 1]]);dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][1]+dis[c[i]][c[i-1]]*(1-f[i-1])+dis[c[i]][d[i-1]]*f[i-1]); dp[i][j][1]=min(dp[i][j][1],dp[i-1][j-1][0]+dis[c[i]][c[i-1]]*(1-f[i])+dis[d[i]][c[i-1]]*f[i]); double tmp=dis[c[i]][c[i-1]](1-f[i])(1-f[i-1])+dis[c[i]][d[i-1]]f[i-1](1-f[i]); tmp+=dis[d[i]][c[i-1]]f[i](1-f[i-1])+dis[d[i]][d[i-1]]*f[i]*f[i-1]; dp[i][j][1]=min(dp[i][j][1],dp[i-1][j-1][1]+tmp); 길 어 보이 지만 실제로는 간단 합 니 다. 거의 네 가지 상황 을 토론 할 뻔 했 습 니 다. 손 이 떨 리 지 않도록 주의 하 시 면 됩 니 다.
#include
#define MIN(x,y,z) min(min(x,y),z)
using namespace std;
int n,m,v,e;
int dis[501][501];
int c[3001],d[3001];
double f[3001];
double dp[3001][3001][2];// i,  j, i    
double ans;
int x,y,z;
int read()
{
    int x=0;
    char c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar();
    return x;
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&v,&e);
    for(int i=1;i<=n;i++)scanf("%d",&c[i]);
    for(int i=1;i<=n;i++)scanf("%d",&d[i]);
    for(int i=1;i<=n;i++)scanf("%lf",&f[i]);
    memset(dis,63,sizeof(dis));
    for(int i=1;i<=v;i++)dis[i][i]=0;
    for(int i=1;i<=e;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        dis[x][y]=min(dis[x][y],z);
        dis[y][x]=min(dis[y][x],z);
    }
    for(int k=1;k<=v;k++)
        for(int i=1;i<=v;i++)
            for(int j=1;j<=v;j++)
                dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    for(int i=1;i<=n;i++)
        for(int j=0;j<=m;j++)
            dp[i][j][0]=dp[i][j][1]=1e10;
    dp[1][0][0]=dp[1][1][1]=0;
    for(int i=2;i<=n;i++)
    {
        for(int j=0;j<=m;j++)
        {
            dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][0]+(double)dis[c[i]][c[i-1]]);
            dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][1]+dis[c[i]][c[i-1]]*(1-f[i-1])+dis[c[i]][d[i-1]]*f[i-1]);
            if(!j)continue;
            dp[i][j][1]=min(dp[i][j][1],dp[i-1][j-1][0]+dis[c[i]][c[i-1]]*(1-f[i])+dis[d[i]][c[i-1]]*f[i]);
            double tmp=dis[c[i]][c[i-1]]*(1-f[i])*(1-f[i-1])+dis[c[i]][d[i-1]]*f[i-1]*(1-f[i]);
            tmp+=dis[d[i]][c[i-1]]*f[i]*(1-f[i-1])+dis[d[i]][d[i-1]]*f[i]*f[i-1];
            dp[i][j][1]=min(dp[i][j][1],dp[i-1][j-1][1]+tmp);
        }
    }
    ans=1e10;
    for(int i=0;i<=m;i++)
        ans=MIN(ans,dp[n][i][0],dp[n][i][1]);
    printf("%.2f",ans);
    return 0;
} 

좋은 웹페이지 즐겨찾기