Description
现有k个串,一个目标串,你从这k个字符串中选取一些字符,组成目标串。现有的k个串中每个串至多可选ai个字符,
而且从第i个串中选取
一个字符耗费i个金币,求组成目标串所消耗最小的金币数,如果不能组成,输出-1;
Input
第一行是目标串,第二行一个k(0<k<=100),接下来k行,每行包括一个现有串,和ai(所有字符串长度不超过100,且非空)
Output
最小消耗的金币
Sample Input
zhonghongyihelafeng
5
zhonghongyihenshuai 10
zhonghongyihennx 10
zhonghongyihenyingjun 10
chuxinggedadiaosi 10
wobuxihuanheichuxing 10
bbaze
3
bzb 2
aeb 3
ba 10
Sample Output
-1
8
Source
zhy
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
#define MAXN 1010
#define MAXM 1000200
#define INF (1<<29)
int sumFlow;
struct Edge{
int u,v,cap,cost;
int next;
}edge[MAXM<<2];
int NE;
int head[MAXN],dist[MAXN],pp[MAXN];
bool vis[MAXN];
char ch[MAXN] ;
int k , n;
void init(){
NE = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int cap,int cost){
edge[NE].u=u;edge[NE].v=v;edge[NE].cap=cap;edge[NE].cost=cost;
edge[NE].next=head[u];head[u]=NE++;
edge[NE].u=v;edge[NE].v=u;edge[NE].cap=0;edge[NE].cost=-cost;
edge[NE].next=head[v];head[v]=NE++;
}
bool SPFA(int s,int t,int n){
int i,u,v;
queue<int> qu;
memset(vis,0,sizeof(vis));
memset(pp,-1,sizeof(pp));
for(i=0;i<=n;i++) dist[i]=INF;
vis[s]=1;dist[s]=0;
qu.push(s);
while(!qu.empty()){
u=qu.front();qu.pop();vis[u]=0;
for(i=head[u];i!=-1;i=edge[i].next){
v=edge[i].v;
if(edge[i].cap && dist[v]>dist[u]+edge[i].cost){
dist[v]=dist[u]+edge[i].cost;
pp[v]=i;
if(!vis[v]){
qu.push(v);
vis[v]=true;
}
}
}
}
if(dist[t]==INF) return false;
return true;
}
int MCMF(int s,int t,int n){//最小费用最大流
int flow = 0; //总流量
int i,minflow,mincost;
mincost = 0;
while(SPFA(s,t,n)){
minflow = INF+1;
for(i=pp[t];i!=-1;i=pp[edge[i].u])
if(edge[i].cap<minflow)
minflow = edge[i].cap;
flow+=minflow;
for(i=pp[t];i!=-1;i=pp[edge[i].u]){
edge[i].cap-=minflow;
edge[i^1].cap+=minflow;
}
mincost += dist[t]*minflow;
}
sumFlow = flow;//最大流
return mincost;
}
int C[33] , cnt[33] , a[111];
int main() {
while(~scanf("%s",ch)) {
int L = strlen(ch);
memset(C,0,sizeof(C));
for(int i=0;i<L;i++) {
int aa = ch[i] - 'a';
C[aa] ++;
}
scanf("%d",&k);
n = 27 * k + 30;
int s = 27 * k + 28 , t = 27 * k + 29;
init();
for(int i=0;i<26;i++) if(C[i]) addedge(s,i,C[i],0);
for(int i=1;i<=k;i++) {
for(int j=0;j<26;j++) {
if(C[j]) addedge(j,i*27+j,C[j],0);
}
scanf("%s",ch);
scanf("%d",&a[i]);
int len = strlen(ch);
memset(cnt,0,sizeof(cnt));
for(int j=0;j<len;j++) {
int aa = ch[j] - 'a';
cnt[aa] ++;
}
for(int j=0;j<26;j++) {
if(cnt[j]) {
addedge(27*i+j,27*i+26,cnt[j],0);
}
//printf("a[i] is %d\n",a[i]);
}
addedge(27*i+26,t,a[i],i);
}
int ans = MCMF(s,t,n);
if(sumFlow == L) printf("%d\n",ans);
else printf("-1\n");
//printf("default : sumFlow is %d , mincost is %d \n",sumFlow,ans);
}
return 0;
}
逆序对
TimeLimit: 1 Second MemoryLimit: 32 Megabyte
Totalsubmit: 20 Accepted: 4
Description
逆序对大家都知道,对于1-n的任意一个排列:a1,a2,a3...an,如果 存在i<j,且ai>aj,则(i,j)称之为一对逆序对。我们常常关心一个排列的逆序对的总数,因为它可以反映一个排列的有序程度。现在 LAM想知道,在1-n的所有排列中,有多少排列的逆序对总数恰好为k。
Input
第一行为正整数T,表示数据组数,接下来T行,每行两个正整数:n,k(n,k<=1000)。
Output
对于每个输入,输出一行表示恰好为k的排列的个数。由于数字可能较大,只需要输出mod10000的结果即可。
Sample Input
1
4 1
Sample Output
3
Source
lrl
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int f[1010][1010];
int sum[1010][1010];
int n , k , T;
int S(int nn , int kk) {
if(kk<0) return 0;
else return sum[nn][kk] % 10000;
}
void init() {
for(int i=1;i<=1000;i++) f[i][0] = sum[i][0] = 1;
for(int i=1;i<=1000;i++)
for(int j=1;j<=1000;j++) {
f[i][j] = (S(i-1,j) - S(i-1,j-i)) % 10000;
while(f[i][j] < 0) f[i][j] += 10000;
sum[i][j] = ( sum[i][j-1] + f[i][j] ) % 10000;
}
}
int main() {
init();
scanf("%d",&T);
while(T--) {
scanf("%d%d",&n,&k);
printf("%d\n",f[n][k]);
}
return 0;
}