有一类糖果,每个糖果有两个属性分别是形状和味道,糖果的形状可以在购买时看到,而味道在购买时是不知道的,约定每种形状的糖果,恰好只有两种不同的味道,并且对于每一种味道,恰好只有两种形状的糖果会有这种味道,现对于每一种形状的糖果,给出四个数t1,n1,t2,n2,表示这种形状的糖果,有n1个的味道是t1,n2个的味道是t2,求至少买多少个糖果,可以保证包所有0--N-1种味道。
首先要确定几点,对于一种形状的糖果有t1,n1,t2,n2,那么我买n1+1个,可以保证买到有味道t2的糖果,买n2+1个,可以保证买到味道t1的糖果,同理,买max(n1,n2)+1个糖果,可以保证买到t1,t2这两种味道的糖果。有了这个前提,我们把味道看做节点,每个形状看做连接t1,t2的边,权值是一个二元组<n1,n2>,由于点数等于边数并且每个节点的度数相同,所以这个图一定是有一个或者几个不向交的环组成的,那么对于每个环,我们就是要用最小的代价,来覆盖所有的点,覆盖的时候,对于一条权值为<x,y>,由s指向t的边,覆盖s的代价是y+1,覆盖t的代价是x+1,同时覆盖s,t的代价是max(x,y)+1。这里可以dp求出最小覆盖的代价,dp[i][j]记录对于第i个点,向前覆盖时j=0,向后覆盖时j=1,对于0--1覆盖和n-1 --- 1覆盖的情况,赋给各自的边界条件,各自做一遍dp,最后去最小值就是覆盖这个环的最小代价。
/*=============================================================================
# Author:Erich
# FileName:
=============================================================================*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#define lson id<<1,l,m
#define rson id<<1|1,m+1,r
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=1ll<<60;
const double PI=acos(-1.0);
int n,m;
struct node
{
int x,y;
node(){
}
node(int a,int b)
{x=a; y=b;
}
};
const int maxn=1050;
vector<int>g[maxn];
vector<node>w[maxn];
class CandyCollection
{
public:
int solve(vector<int> t1,vector<int> n1,vector<int> t2,vector<int> n2)
{
n=t1.size();
for (int i=0; i<n; i++)
{
int x=t1[i],y=t2[i];
int wx=n1[i],wy=n2[i];
g[x].push_back(y);
w[x].push_back(node(wx,wy));
g[y].push_back(x);
w[y].push_back(node(wy,wx));
}
int ans=0;
for (int i=0; i<n; i++)
if (g[i].size()==2)
{
int cur=i,last=-1;
int tmp=0;
vector<node> path(0);
while(true)
{
if (g[cur][0]!=last)
{
path.push_back(w[cur][0]);
last=cur;
cur=g[cur][0];
}
else
{
path.push_back(w[cur][1]);
last=cur;
cur=g[cur][1];
}
g[last].clear();
if (cur==i) break;
}
int dp[1050][2];
memset(dp,0x3f,sizeof dp);
int l=path.size();
dp[0][1]=path[0].y+1;
dp[1][1]=max(path[0].x,path[0].y)+1;
for (int j=0; j<l; j++)
{
dp[j+1][0]=min(dp[j+1][0],dp[j][1]);
dp[j+1][0]=min(dp[j+1][0],dp[j][0]+path[j].y+1);
dp[j+1][1]=min(dp[j+1][1],dp[j][0]+max(path[j].x,path[j].y)+1);
dp[j+1][1]=min(dp[j+1][1],dp[j][1]+path[j].x+1);
}
tmp=min(dp[l][0],dp[l][1]);
memset(dp,0x3f,sizeof dp);
dp[1][1]=path[0].x+1;
dp[1][0]=0;
for (int j=1; j<l; j++)
{
dp[j+1][0]=min(dp[j+1][0],dp[j][1]);
dp[j+1][0]=min(dp[j+1][0],dp[j][0]+path[j].y+1);
dp[j+1][1]=min(dp[j+1][1],dp[j][0]+max(path[j].x,path[j].y)+1);
dp[j+1][1]=min(dp[j+1][1],dp[j][1]+path[j].x+1);
}
tmp=min(tmp,dp[l][1]);
ans+=tmp;
}
return ans;
}
}work;