Back and Forth —— set的删除操作
作者:互联网
Description
Input
Output
Sample Input
1 1 1 1 1 1 1 1 1 2
5 5 5 5 5 5 5 5 5 5
Sample Output
5
Hint
题意:
一个人有两个存牛奶的仓库,每个仓库里有10个桶,一开始每个仓库都有1000的牛奶,星期二他随便从第一个仓库里拿了一个桶装满牛奶倒到第二个仓库,星期三从第二个仓库随便拿一个桶(有可能是星期二拿来的桶)装满倒到第一个仓库里,周四从仓库一到仓库二,周五从仓库二到仓库一,问你最后仓库一里面的牛奶有多少种可能。
题解:
这道水题真的被坑死了,做了两个小时,就是因为对set的操作不熟悉,然后又想一些有的没的。。
枚举每一种情况,把第一个的某一个放到第二个里面,然后把它erase掉,然后dfs完之后又放回来,这样重复,注意就是 5 5 5的情况,你有可能把5又重新放到最后面,所以你需要记录当前枚举到了第几个。。但是恕我直言,写我下面这种dfs模拟的,都是智障,为什么有更简单暴力的算法不用?暴力总共有3种情况,第一种是一个桶赖慧娜4次,第二种是两个桶每个来回拿两次,第三种是每个桶都被拿了一次
set:
#include<bits/stdc++.h>
using namespace std;
int a[15],b[15];
multiset<int>aa,bb;
set<int>ans;
int vis[5][105];
void dfs(int sum,int t)
{
if(t==4)
{
ans.insert(sum);
//cout<<sum<<endl;
return ;
}
if(t%2)
{
int cnt=0;
while(cnt<bb.size())
{
multiset<int>::iterator it=bb.begin();
for(int i=1;i<=cnt;i++)
it++;
cnt++;
int v=*it;
aa.insert(*it);
bb.erase(it++);
dfs(sum+v,t+1);
aa.erase(aa.find(v));
bb.insert(v);
}
}
else
{
int cnt=0;
while(cnt<aa.size())
{
multiset<int>::iterator it=aa.begin();
for(int i=1;i<=cnt;i++)
it++;
cnt++;
int v=*it;
bb.insert(v);
aa.erase(it++);
dfs(sum-v,t+1);
aa.insert(v);
bb.erase(bb.find(v));
}
}
}
int main()
{
for(int i=1;i<=10;i++)
scanf("%d",&a[i]),aa.insert(a[i]);
for(int j=1;j<=10;j++)
scanf("%d",&b[j]),bb.insert(b[j]);
dfs(1000,0);
printf("%d\n",ans.size());
return 0;
}
暴力:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
int a[15],b[15];
int vis[400];
//200为0
int main(){
for(int i=1;i<=10;i++) scanf("%d",&a[i]);
for(int i=1;i<=10;i++) scanf("%d",&b[i]);
vis[200]=1;
int ans=1;
for(int aa=1;aa<=10;aa++){
for(int bb=1;bb<=10;bb++){
int nows=200+b[bb]-a[aa];
if(!vis[nows]){
vis[nows]=1;
ans++;
}
}
}
for(int a1=1;a1<=10;a1++){
for(int a2=a1+1;a2<=10;a2++){
for(int b1=1;b1<=10;b1++){
for(int b2=b1+1;b2<=10;b2++){
int nows=200+b[b1]+b[b2]-a[a1]-a[a2];
if(!vis[nows]){
vis[nows]=1;
ans++;
}
}
}
}
}
printf("%d",ans);
return 0;
}
标签:set,15,int,一个桶,Back,dfs,仓库,Forth 来源: https://blog.csdn.net/tianyizhicheng/article/details/88371740