CF543C 让所有的串成为独特的串的最小代价(状压dp,贪心)

来源:互联网 发布:vb正则表达式语法 编辑:程序博客网 时间:2024/05/21 10:53

题意(转):给定n个长度为m的字符串。为了让每个字符串变为独特的(该字符串的某一个位置存在一个字符ch,其他串的这个位置都不存在这个字符ch),你可以改变某些字符串的某些字符。现在告诉你改变每个字符的代价,求让所有的串成为独特的串的最小代价。

两个转移(对某行某列的字母):

1、直接修改本行的字母

2、把所有在该列拥有该字母的行都修改成别的字母。只需修改x-1个,留下权值最大的那个(贪心)。

其中1是必要的。因为你不知道还有哪几行等待被拯救。2是圣母的做法,在待拯救的行占所有行比例较少时适用1。比如对这个:

http://blog.csdn.net/stl112514/article/details/47125275

实际上发生了【某列的某种字母(x个)改变其中x-1个】的操作就不会发生【改变当前单个字母】的操作。所以,不需要考虑修改当前字母后对这一列其他同原字母一样的行的影响,即后者对前者的影响。

#include <bits/stdc++.h>#define ll long longusing namespace std;int dp[(1<<20)+5];string x[22];int y[22][22];pair<int,int> w[22][22]; int main(){int n,m;cin>>n>>m;for(int i=0;i<n;++i){cin>>x[i];}for(int i=0;i<n;++i){for(int j=0;j<m;++j){cin>>y[i][j];}}for(int i=0;i<n;++i){for(int j=0;j<m;++j){int maxx=0;char c=x[i][j];if(w[j][c-'0'].second>0)continue;for(int k=0;k<n;++k){if(x[k][j]==c){w[j][c-'0'].first+=y[k][j];w[j][c-'0'].second+=(1<<k);if(y[k][j]>maxx)maxx=y[k][j];}}w[j][c-'0'].first-=maxx;}}for(int i=1;i<(1<<n);++i)dp[i]=1000000000;for(int i=0;i<(1<<n);++i){for(int j=0;j<n;++j){if(i&(1<<j))continue;for(int k=0;k<m;++k){//下面两个是冲突的,换句话说,实际上发生了【某列的某种字母(x个)改变其中x-1个】的操作就不会发生【改变当前单个字母】的操作 dp[i|(1<<j)]=min(dp[i|(1<<j)],dp[i]+y[j][k]);int a=w[k][x[j][k]-'0'].first,b=w[k][x[j][k]-'0'].second;dp[i|b]=min(dp[i|b],dp[i]+a);}}}cout<<dp[(1<<n)-1]<<endl;return 0;}


1 0
原创粉丝点击