【DP】hihocoder #1170: 로봇

2383 단어 dphihocoer
16개의 색 상압에 대해 dp[i]는 2진법 i개의 색을 사용하여 제목의 요구를 만족시키는 최소 비용을 나타낸다.그러면 매번 우리는 한 가지 색깔을 골라서 이 색깔의 맨 앞에 놓고 옮길 수 있다...먼저 j가 i 앞에 놓는 비용을 미리 처리할 수 있다. 바로 각 j 앞에 몇 개의 i의 총계가 있다...
#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <math.h>
#include <time.h>
#define maxn 100005
#define maxm 200005
#define eps 1e-7
#define mod 1000000007
//#define INF 0x3f3f3f3f
#define PI (acos(-1.0))
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R
#define pii pair<int, int>
#pragma comment(linker, "/STACK:16777216")
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;
LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}
LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}
//head

const LL INF = 0x3f3f3f3f3f3f3f3fLL;
LL dp[1 << 17];
LL cost[20][20];
vector<int> g[20];
int n, kk;

void work(int _)
{
	int x;
	scanf("%d%d", &n, &kk);
	for(int i = 0; i < kk; i++) g[i].clear();
	for(int i = 1; i <= n; i++) {
		scanf("%d", &x);
		g[--x].push_back(i);
	}
	
	for(int i = 0; i < kk; i++)
		for(int j = 0; j < kk; j++) {
			if(i == j) continue;
			LL sum = 0, cnt = 0;
			for(int k = 0; k < g[j].size(); k++) {
				while(g[i].size() > cnt && g[i][cnt] < g[j][k]) cnt++;
				sum += cnt;
			}
			cost[j][i] = sum;
		}
	memset(dp, 0x3f, sizeof dp);
	dp[0] = 0;
	for(int i = 0; i < (1 << kk); i++) {
		if(dp[i] == INF) continue;
		for(int j = 0; j < kk; j++) {
			if((i >> j) & 1) continue;
			LL sum = 0;
			for(int k = 0; k < kk; k++) {
				if(((i >> k) & 1) == 0) continue;
				sum += cost[j][k];
			}
			dp[i | (1 << j)] = min(dp[i | (1 << j)], dp[i] + sum);
		}
	}
	printf("Case #%d: %lld
", _, dp[(1 << kk) - 1]); } int main() { int _; scanf("%d", &_); for(int i = 1; i <= _; i++) work(i); return 0; }

좋은 웹페이지 즐겨찾기