ural 2071 - Juice Cocktails

题意:有n杯调和果汁,用A,B,P三种果汁调,每一次可以往一个连续区间添加一种果汁,问最少需要加多少次。

n很大,最大10的五次方,但是状态数量很有限,只有7种,相同的果汁肯定要连续放才能使添加次数最少,而且连续相同的果汁不管有多少,总是跟一杯的时候结果相同,那么直接对于七种状态全排列找最优解就行了。

代码因为时间比较紧,写的比较挫一点,可以进一步优化。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
using namespace std;
map<string, int> s;
string rs[10];
map<string, int>::iterator p;
void init() {
    s["A"] = 0;
    rs[0] = "A";
    s["AB"] = 1;
    rs[1] = "AB";
    rs[2] = "ABP";
    rs[3] = "AP";
    rs[4] = "B";
    rs[5] = "BP";
    rs[6] = "P";
    s["ABP"] = 2;
    s["AP"] = 3;
    s["B"] = 4;
    s["BP"] = 5;
    s["P"] = 6;
}
int id[10];
vector<int> dx[10];
int main() {
    init();
    int n, i, j, k;
    string a;
    while(~scanf("%d", &n)) {
        for(i = 0; i < 10; i++)
            dx[i].clear();
        for(i = 0; i < n; i++) {
            cin >> a;
            int b = s[a];
            dx[b].push_back(i + 1);
        }
        int m = 0;
        for(i = 0; i < 7; i++) {
            if(dx[i].size()) {
                id[m++] = i;
            }
        }
        int ans = 100;
        do {
            int d = id[0];
            int t = rs[d].size();
            for(i = 1; i < m; i++) {
                d = id[i];
                for(j = 0; j < rs[d].size(); j++) {
                    for(k = 0; k < rs[id[i - 1]].size(); k++) {
                        if(rs[d][j] == rs[id[i - 1]][k])
                            break;
                    }
                    if(k == rs[id[i - 1]].size())
                        t++;
                }
            }
            if(t < ans)
                ans = t;
        }while(next_permutation(id, id + m));
        sort(id, id + m);
        do {
            int d = id[0];
            int t = rs[d].size();
            for(i = 1; i < m; i++) {
                d = id[i];
                for(j = 0; j < rs[d].size(); j++) {
                    for(k = 0; k < rs[id[i - 1]].size(); k++) {
                        if(rs[d][j] == rs[id[i - 1]][k])
                            break;
                    }
                    if(k == rs[id[i - 1]].size())
                        t++;
                }
            }
            if(t == ans) {
                int is = 0;
                printf("%d\n", ans);
                for(i = 0; i < m; i++) {
                    for(j = 0; j < dx[id[i]].size(); j++) {
                        if(is)
                            printf(" ");
                        else is = 1;
                        printf("%d", dx[id[i]][j]);
                    }
                }
                printf("\n");
                break;
            }
        }while(next_permutation(id, id + m));
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值