题解:
状压集合\(DP\),状态\(F[s]\),表示完成\(s\)这个集合的填充最少需要多少步,预先预处理,将所有回文串标记为\(true\),\(DP\)时外循环枚举0-全集,内循环枚举外循环的补集的子集;
\(code\):
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<ctype.h>
#define inf 1e9+9
#define ll long long
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(x=0,flag=1):(x=tt-'0');
while(isdigit(tt=gc())) x=x*10+tt-'0';
if(flag) x=-x;
}
int n,tot;
int f[1<<17];
bool book[1<<17];
char a[20];
char tmp1[20],tmp2[20];
bool ok(int s)
{
int cnt=0,now=0;
while(s)
{
now++;
if(s&1) tmp1[++cnt]=a[now];
s>>=1;
}
for(int i=cnt;i>=1;i--)
tmp2[cnt-i+1]=tmp1[i];
for(int i=1;i<=cnt;i++)
if(tmp1[i]!=tmp2[i]) return 0;
return 1;
}
int main()
{
freopen("piece.in","r",stdin);
freopen("piece.out","w",stdout);
char tt;
while((tt=gc())!='\n') a[++n]=tt;
tot=(1<<n)-1;
for(int i=1;i<=tot;i++) f[i]=inf;
for(int s=1;s<=tot;s++)
if(ok(s)) book[s]=1;
for(int s1=0;s1<=tot;s1++)
{
int s=s1^tot;
for(int s2=s;s2;s2=(s2-1)&s)
{
if(!book[s2]) continue;
f[s1|s2]=min(f[s1|s2],f[s1]+1);
}
}
printf("%d",f[tot]);
}
题解:
优化\(DP\),状态很好想\(F[i][j]\),表示第n秒停在m号位置可以消耗的最少体力,状态转移:\(F[i][j]=min{F[i][j],F[i-1][k]+pos+cost},(1<=k<=m)\),显然时间复杂度为\(O(N*M^2)\),对取最小值进行优化,打开绝对值,分为两个单调队列或优先队列讨论;
\(code:\)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<ctype.h>
#define inf 1e9+9
#define ll long long
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc() {
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x) {
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(x=0,flag=1):(x=tt-'0');
while(isdigit(tt=gc())) x=x*10+tt-'0';
if(flag) x=-x;
}
int n,m,x,ans,f[55][5005];
struct node {
int pos,cost;
inline node(int a=0,int b=0) {
pos=a;
cost=b;
}
bool operator<(node a)const {
return pos<a.pos;
}
} a[55][5005];
int main() {
freopen("dragon.in","r",stdin);
freopen("dragon.out","w",stdout);
read(n),read(m),read(x);
for(int i=1; i<=n; i++ )
for(int j=1; j<=m; j++ )
read(a[i][j].pos);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
read(a[i][j].cost);
for(int i=1; i<=n; i++) sort(a[i]+1,a[i]+m+1);
for(int j=1; j<=m; j++)
f[1][j]=abs(x-a[1][j].pos)+a[1][j].cost;
for(int i=2; i<=n; i++ ) {
ans=inf;
for(int j=1,k=1; j<=m; j++ )
{
for( ;k<=m&&a[i-1][k].pos<=a[i][j].pos; k++ )
{
int t=f[i-1][k]-a[i-1][k].pos;
ans=min(ans,t);
}
f[i][j]=ans+a[i][j].pos+a[i][j].cost;
}
ans=inf;
for(int j=m,k=m; j; j-- ) {
for(; k&&a[i-1][k].pos>a[i][j].pos; k--)
{
int t=f[i-1][k]+a[i-1][k].pos;
ans=min(ans,t);
}
f[i][j]=min(f[i][j],ans-a[i][j].pos+a[i][j].cost);
}
}
ans=inf;
for(int j=1; j<=m; j++) ans=min(ans,f[n][j] );
printf("%d",ans);
}
题解:
树形\(DP\),\(30\)分做法是\(N^2\)爆搜,\(50\)分做法为\(O(N)\)处理类似最大深度和问题,\(100\)分做法待补;
\(30\)分\(code:\)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<ctype.h>
#define ll long long
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(x=0,flag=1):(x=tt-'0');
while(isdigit(tt=gc())) x=x*10+tt-'0';
if(flag) x=-x;
}
struct node{
ll x,len;
inline node(ll a=0,ll b=0)
{
x=a;
len=b;
}
inline bool operator<(node a)const
{
return len<a.len;
}
};
ll n,m;
ll sz[10005],f[10005];
vector<node>G[10005];
void dfs(ll x,ll pre,ll dis)
{
f[x]=dis;
for(int i=G[x].size()-1;i>=0;i--)
{
int p=G[x][i].x;
int len=G[x][i].len;
if(p==pre) continue;
dfs(p,x,dis+len);
}
}
int main()
{
freopen("warehouse.in","r",stdin);
freopen("warehouse.out","w",stdout);
read(n),read(m);
for(int i=1;i<n;i++)
{
ll x,y,z;
read(x),read(y),read(z);
G[x].push_back(node(y,z));
G[y].push_back(node(x,z));
}
for(int i=1;i<=n;i++)
{
memset(f,0,sizeof(f));
ll ans=0;
dfs(i,0,0);
for(int j=1;j<=n;j++)
if(i!=j) ans+=(f[j]^m);
printf("%lld\n",ans);
}
}