题意:有m道题,要分给n个朋友解决,每个朋友有不同的条件,酬劳,且每个朋友要至少k个显示器连接作者电脑才肯帮忙,所以作者需要买至少k个显示器。求解决所有问题所需最少的钱。
分析:可以状压20个问题,实际是二维,dp[i][s]表示用前i个人解决s(二进制,解决问题的集合)所需最少钱,由于爆内存可省略第一维。正确的做法是先根据显示器数目将朋友排序,我纠结的是不排序维护一个mx数组表示s状态显示器的最大值会wa在第24发。
正确代码:
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 2e18
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef pair<int,int> pii;
typedef unsigned long long ULL;
typedef long long LL;
const int maxn=100005;
int n,m,b;
LL dp[1<<20];
struct Node
{
int x;
int k;
int s;
bool operator<(const Node& a)const
{
return k<a.k;
}
}fr[105];
int main()
{
scanf("%d%d%d",&n,&m,&b);
int u;
for(int i=1;i<=n;i++){
scanf("%d%d%d",&fr[i].x,&fr[i].k,&u);
int ans=0;
int d;
for(int j=0;j<u;j++)
{
scanf("%d",&d);
ans^=(1<<(d-1));
}
fr[i].s=ans;
}
sort(fr+1,fr+n+1);
dp[0]=0;
for(int i=1;i<(1<<m);i++)
dp[i]=inf;
LL res=inf;
for(int i=1;i<=n;i++){
for(int j=0;j<(1<<m);j++){
dp[j|fr[i].s]=min(dp[j|fr[i].s],dp[j]+fr[i].x);//正推
}
res=min(res,dp[(1<<m)-1]+fr[i].k*(LL)b);
}
if(res==inf)
res=-1;
cout<<res;
return 0;
}
错误代码:
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 2e18
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef pair<int,int> pii;
typedef unsigned long long ULL;
typedef long long LL;
const int maxn=100005;
int n,m,b;
LL dp[1<<20];
int mx[1<<20];
struct Node
{
int x;
int k;
int s;
bool operator<(const Node& a)const
{
return k<a.k;
}
}fr[105];
int main()
{
scanf("%d%d%d",&n,&m,&b);
int u;
for(int i=1;i<=n;i++){
scanf("%d%d%d",&fr[i].x,&fr[i].k,&u);
int ans=0;
int d;
for(int j=0;j<u;j++)
{
scanf("%d",&d);
ans^=(1<<(d-1));
}
fr[i].s=ans;
}
//sort(fr+1,fr+n+1);
dp[0]=0;
mx[0]=0;
for(int i=1;i<(1<<m);i++){
dp[i]=inf;
mx[i]=-1e9;
}
LL res=inf;
for(int i=1;i<=n;i++){
for(int j=0;j<(1<<m);j++){
if(dp[j]<inf){
LL sum=dp[j]+fr[i].x;
if(fr[i].k>mx[j])
sum+=(fr[i].k-mx[j])*(LL)b;
if(sum<dp[j|fr[i].s]){
dp[j|fr[i].s]=sum;
mx[j|fr[i].s]=max(fr[i].k,mx[j]);
}
}
}
res=min(res,dp[(1<<m)-1]);
}
if(res==inf)
res=-1;
cout<<res;
return 0;
}