状态压缩。路径的选择和每条路径内宝物的选择是没有必然关联的,分开处理。选择路径时直接状态压缩。在处理路径内部选择时,出现了问题。一开始想复杂了,比如选下a,再选下b,某一个增加以后会对后面产生怎样的影响。。。其实必然是先选完一种再选另一种。一次选择时,选a时,b可以增值x次,共x*va点,选b,则后面x次拿a会增值vb点,共x*vb;所以选择是固定的,只与增加值大小有关。另zoj64位用lld输出。
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
#define INF 1000000007
#define N 1000
int n;
struct SSS{
LL va;
LL vb;
LL x;
LL y;
}s[20];
LL val[20];
LL dp[1 << 15];
LL suma[1 << 15];
LL sumb[1 << 15];
int main(){
while(scanf("%d", &n) != EOF){
for(int i = 0; i < n; i++){
scanf("%lld%lld%lld%lld", &s[i].va, &s[i].vb, &s[i].x, &s[i].y);
}
memset(dp, 0, sizeof(dp));
memset(val, 0, sizeof(val));
suma[0] = 0;
sumb[0] = 0;
for(int i = 0; i < (1 << n); i++){
for(int j = 0; j < n; j++){
if(i & (1 << j))continue;
suma[i | (1 << j)] = suma[i] + s[j].y * s[j].vb;
sumb[i | (1 << j)] = sumb[i] + s[j].x * s[j].va;
}
}
for(int i = 0; i < n; i++){
if(s[i].va >= s[i].vb){
val[i] = s[i].x * s[i].y * s[i].va;
}
else {
val[i] = s[i].x * s[i].y * s[i].vb;
}
}
LL mv = 0;
for(int i = 0; i < (1 << n); i++){
for(int j = 0; j < n; j++){
if(dp[i | (1 << j)] > mv)mv = dp[i | (1 << j)];
if(i & (1 << j))continue;
if(dp[i | (1 << j)] <= dp[i] + val[j] + suma[i] * s[j].x + sumb[i] * s[j].y){
dp[i | (1 << j)] = dp[i] + val[j] + suma[i] * s[j].x + sumb[i] * s[j].y;
}
}
}
printf("%lld\n", mv);
}
return 0;
}